PIPS
for_to_do_or_while_loops.c
Go to the documentation of this file.
1 /*
2 
3  $Id: for_to_do_or_while_loops.c 23470 2018-06-02 13:39: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 /** Some passes to transform for-loops into do-loops or while-loops that
28  may be easier to analyze by PIPS.
29 */
30 
31 #include "genC.h"
32 #include "linear.h"
33 #include "ri.h"
34 #include "ri-util.h"
35 #include "control.h"
36 #include "misc.h"
37 #include "pipsdbm.h"
38 #include "resources.h"
39 
40 
41 
42 
43 /* Test if the final value @param li of a for-loop is static.
44 
45  @return:
46  - true if the final value of a for-loop is static
47 
48  - pub is the new expression of the final value
49 
50  - *is_upper_p is set to true if the final value is upper-bound (index
51  is probably increasing) and to false if the final value is
52  lower-bound (index is probably decreasing)
53 
54  Depending on cond, the so-called upper bound may end up being a lower
55  bound with a decreasing step loop.
56  */
58  entity li,
59  bool * is_upper_p,
60  expression * pub)
61 {
62  bool success = false;
63  syntax cond_s = expression_syntax(cond);
64  bool strict_p = false;
65 
66  /* ifdebug(5) { */
67  /* pips_debug(5, "Begin with expression\n"); */
68  /* print_expression(cond); */
69  /* } */
70 
71  if(syntax_call_p(cond_s)) {
72  call c = syntax_call(cond_s);
73  entity op = call_function(c);
74 
75  /* Five operators are accepted */
78  // FI: wrong result for !=; no way to derive a correct bound
79  // without information about the increment
80  /*|| ENTITY_NON_EQUAL_P(op)*/ ) {
83  syntax e1_s = expression_syntax(e1);
84  syntax e2_s = expression_syntax(e2);
85 
86  strict_p = ENTITY_LESS_THAN_P(op) || ENTITY_GREATER_THAN_P(op) || ENTITY_NON_EQUAL_P(op);
87 
88  if (syntax_reference_p(e1_s)
89  && reference_variable(syntax_reference(e1_s)) == li ) {
90  *is_upper_p = ENTITY_LESS_THAN_P(op)
92  *pub = convert_bound_expression(e2, *is_upper_p, !strict_p);
93  success = true;
94  }
95  else if (syntax_reference_p(e2_s)
96  && reference_variable(syntax_reference(e2_s)) == li) {
97  *is_upper_p = ENTITY_GREATER_THAN_P(op)
99  *pub = convert_bound_expression(e1, *is_upper_p, !strict_p);
100  success = true;
101  }
102  }
103  }
104 
105  ifdebug(5) {
106  if(success) {
107  /* pips_debug(5, "Static final value found!\n" */
108  /* "\tEnd with expression:\n"); */
109  /* print_expression(*pub); */
110  pips_debug(5, "Loop counter is probably %s\n",
111  *is_upper_p ? "increasing" : "decreasing");
112  pips_debug(5, "Loop condition is strict (< or > instead of <= or >=) : %s\n", bool_to_string(strict_p));
113  }
114  else
115  pips_debug(5, "End: no final bound available\n");
116  }
117 
118  return success;
119 }
120 
121 
122 /*
123  Test if a for-loop incrementation expression is do-loop compatible
124  (i.e. the number of iterations can be computed before entering the
125  loop and hence the increment sign is known and the increment is
126  unchanged by the loop iterations) and, if yes, compute the
127  increment expression. We *have* to fail on symbolic increments with
128  unknown sign because we won't be able to restore a correct code.
129 
130  Most of this could be trivial by using the transformers but this
131  function is to be used from the controlizer where the semantics
132  informations are far from being available yet.
133 
134  @param incr for-loop incrementation expression
135  @param li is the index variable
136 
137  @return true if the incrementation is do-loop compatible \`a la Fortran
138  - @param is_increasing_p is set to true is the loop index is increasing
139  - @param pincrement is generated with the detected increment value expression
140  */
142  entity li,
143  bool * is_increasing_p,
144  expression * pincrement)
145 {
146  bool success = false;
147  syntax incr_s = expression_syntax(incr);
148 
149  if (syntax_call_p(incr_s)) {
150  call incr_c = syntax_call(incr_s);
151  entity op = call_function(incr_c);
152  if (! ENDP(call_arguments(incr_c))) {
153  expression e = EXPRESSION(CAR(call_arguments(incr_c)));
154 
155  /* The expression should concern the loop index: */
157  /* Look for i++ or ++i: */
159  * is_increasing_p = true;
160  * pincrement = int_to_expression(1);
161  success = true;
162  pips_debug(5, "Increment operator found!\n");
163  }
164  /* Look for i-- or --i: */
165  else if ((ENTITY_POST_DECREMENT_P(op) || ENTITY_PRE_DECREMENT_P(op))) {
166  * is_increasing_p = false;
167  * pincrement = int_to_expression(-1);
168  success = true;
169  pips_debug(5, "Decrement operator found!\n");
170  }
171  else if (! ENDP(CDR(call_arguments(incr_c)))) {
172  /* Look for stuff like "i += integer". Get the rhs: */
173  /* This fails with floating point indices as found in
174  industrial code and with symbolic increments as in
175  "for(t=0.0; t<t_max; t += delta_t). Floating point
176  indices should be taken into account. The iteration
177  direction of the loop should be derived from the bound
178  expression, using the comparison operator. */
179  expression inc_v = EXPRESSION(CAR(CDR(call_arguments(incr_c))));
180  bool entity_plus_update_p = ENTITY_PLUS_UPDATE_P(op);
181  bool entity_minus_update_p = ENTITY_MINUS_UPDATE_P(op);
182  if ( (entity_plus_update_p||entity_minus_update_p) ) {
183  if(expression_constant_p(inc_v)) {
184  int v = expression_to_int(inc_v);
185  // bool eval_p = expression_integer_value(inc_v);
186  //pips_assert("The expression can be evaluated",
187  // eval_p);
188  if (v != 0) {
189  int sign = entity_plus_update_p ? 1 : -1 ;
190  * pincrement = int_to_expression(sign * v);
191  success = true;
192  if (v > 0 ) {
193  * is_increasing_p = entity_plus_update_p;
194  pips_debug(5, "Found += with positive increment!\n");
195  }
196  else {
197  * is_increasing_p = entity_minus_update_p;
198  pips_debug(5, "Found += with negative increment!\n");
199  }
200  }
201  }
202  /* SG: we checked the no-write-effect-on-increment earlier, we can go on safely,
203  * but we will not know if the increment is positive or not, assume yes ?
204  */
205  else {
206  // We must know the sign of inc_v and be
207  // sure that its value cannot be changed by the loop body
208  bool pos_p = positive_expression_p(inc_v);
209  bool neg_p = negative_expression_p(inc_v);
210  if(pos_p || neg_p) {
211  if(entity_minus_update_p) {
212  // FI: I assume we are not dealing with pointers
214  * pincrement = MakeUnaryCall(uminus, copy_expression(inc_v));
215  }
216  else
217  * pincrement = copy_expression(inc_v);
218  *is_increasing_p = (entity_plus_update_p && pos_p)
219  || (entity_minus_update_p && neg_p);
220  success = true;
221  }
222  else
223  // Here we have to fail to be safe ! See validation/C_syntax/decreasing_loop01
224  success = false;
225  }
226  }
227  else {
228  /* Look for "i = i + v" (only for v positive here...)
229  or "i = v + i": */
231  if (inc_v != expression_undefined ) {
233  int v = expression_to_int(inc_v);
234  if (v != 0) {
235  * pincrement = inc_v;
236  success = true;
237  if (v > 0 ) {
238  * is_increasing_p = true;
239  pips_debug(5, "Found \"i = i + v\" or \"i = v + i\" with positive increment!\n");
240  }
241  else {
242  * is_increasing_p = false;
243  pips_debug(5, "Found \"i = i + v\" or \"i = v + i\" with negative increment!\n");
244  }
245  }
246  }
247  /* SG: we checked the no-write-effect-on-increment earlier, we can go on safely,
248  * but we will not know if the increment is positive or not, assume yes ?
249  */
250  else {
251  * pincrement = copy_expression(inc_v);
252  if(positive_expression_p(inc_v)) {
253  * is_increasing_p = true;
254  success = true;
255  }
256  else if(negative_expression_p(inc_v)) {
257  * is_increasing_p = false;
258  success = true;
259  }
260  else
261  // Here we have to fail to be safe ! See validation/C_syntax/decreasing_loop01
262  success = false;
263  }
264  }
265  /* SG: i am duplicating code, next generation of phd will clean it */
266  else {
268  if (inc_v != expression_undefined ) {
271  int v = expression_to_int(inc_v);
272  if (v != 0) {
273  * pincrement = inc_v;
274  success = true;
275  if (v <= 0 ) {
276  * is_increasing_p = true;
277  pips_debug(5, "Found \"i = i - v\" or \"i = v - i\" with positive increment!\n");
278  }
279  else {
280  * is_increasing_p = false;
281  pips_debug(5, "Found \"i = i - v\" or \"i = v - i\" with negative increment!\n");
282  }
283  }
284  }
285  /* SG: we checked the no-write-effect-on-increment earlier, we can go on safely,
286  * but we will not know if the increment is positive or not, assume yes ?
287  */
288  else {
289  // FI: I'm lost here
290  * pincrement = inc_v;
291  if(positive_expression_p(inc_v)) {
292  * is_increasing_p = false;
293  success = true;
294  }
295  else if(negative_expression_p(inc_v)) {
296  * is_increasing_p = true;
297  success = true;
298  }
299  else
300  // Here we have to fail to be safe!
301  success = false;
302  }
303  }
304  }
305  }
306  }
307  }
308  }
309  }
310  return success;
311 }
312 
313 /**
314  * parameter of effect guesser
315  */
316 typedef struct {
317  entity target; ///< entity to find effect on
318  bool written; ///< wheter the entity seems written
319 } guesser_param;
320 
321 /**
322  * Try hard to guess wether the call @param c writes @param p
323  * Note that it is just a guess and may be wwrong
324  *
325  * This function only exists because effects are not available in the
326  * controlizer moreover, no aliasing information is available, so the
327  * guess **may** be wrong
328  */
330 {
331  entity op = call_function(c);
332  list args = call_arguments(c);
333  if( ENTITY_ASSIGN_P(op) ||
339  ENTITY_ADDRESS_OF_P(op)|| // FI: pretty pessimistic; see Rice/malloc02.c
342  ) {
343  expression lhs = EXPRESSION(CAR(args));
344  if(expression_reference_p(lhs) &&
346  {
347  p->written=true;
348  gen_recurse_stop(0);
349  }
350  }
351  return true;
352 }
353 
354 /**
355  * classical statement walker, gen_recurse does not dive into statement declarations
356  */
358 {
360  if( !value_undefined_p(entity_initial(e) ) ) {
362  }
363  return true;
364 }
365 
366 /**
367  * call guess_write_effect_on_entity_walker on each call of @param exp
368  * in order to guess write effect on @param loop_index
369  *
370  * @return true if we are sure the entity was written, false otherwise, let's be optimistic :)
371  */
373 {
374  guesser_param p = { loop_index, false };
378  0);
379  return p.written;
380 
381 
382 }
383 
384 /* Check comma expressions used for initialization
385  *
386  * Assuming loop_index is a potential do loop index, and init a comma
387  * expression, do we have subexpressions after the loop_index
388  * initialization that may use this index? If yes, the loop cannot be
389  * transformed into a DO loop, because this subexpression will be
390  * moved before the loop index initialization. Or the loop index
391  * initialization should be replicated before the loop.
392  *
393  * Example (SPEC2006, milc):
394  *
395  * for (i = parity==0x01?even_sites_on_node:0, s = &lattice[i];
396  * i<(parity==0x02?even_sites_on_node:sites_on_node);
397  * i++, s++) {
398  *
399  * s = &lattice[i] is going to be placed ahead of i's own initialization.
400  *
401  * In other words, the loop can be changed in different ways:
402  *
403  * - the loop is converted into a while loop with the initialization
404  * expression moved into a statement (easy, alreayd implemented,
405  * safe)
406  *
407  * - the conversion into a DO loop is performed, but *all*
408  * initializations are moved into a statement and the new
409  * initialization expression is "loop_init = loop_init" to satisfy the
410  * do loop semantics (a new implementation is required).
411  */
413 {
414  bool guess_p = false;
415  if(expression_call_p(init)) {
417  entity f = call_function(c);
418  if(ENTITY_COMMA_P(f)) {
419  bool write_found_p = false;
420  list el = call_arguments(c);
421  FOREACH(EXPRESSION, e, el) {
422  if(!write_found_p && guess_write_effect_on_entity(e, loop_index))
423  write_found_p = true;
424  else if(write_found_p) {
426  FOREACH(REFERENCE, r, rl) {
427  guess_p = reference_variable(r)==loop_index;
428  if(guess_p)
429  break;
430  }
431  if(guess_p) {
432  gen_free_list(rl); // Just the spine...
433  break;
434  }
435  }
436  }
437  }
438  }
439  return guess_p;
440 }
441 
442 /**
443  * guess the increment of a loop
444  * the condition is: the increment must be a reference that is constant in the loop body
445  *
446  * @param e candidate expression
447  * @param loop_index entity guessed as index
448  * @param body loop body
449  *
450  * @return selected increment expression
451  */
452 static
454 {
455  if(expression_call_p(e))
456  {
457  call c = expression_call(e);
458  list args = call_arguments(c);
459  entity op = call_function(c);
463  ENTITY_ASSIGN_P(op) /* this one needs further processing */ )
464  {
465  expression lhs = EXPRESSION(CAR(args));
466  if(expression_reference_p(lhs) &&
468  {
469  if(!ENTITY_ASSIGN_P(op)) {
470  return e;
471  }
472  else {
473  expression rhs = EXPRESSION(CAR(CDR(args)));
474  if(expression_call_p(rhs))
475  {
476  call rhs_c = expression_call(rhs);
477  entity rhs_op = call_function(rhs_c);
478  list rhs_args = call_arguments(rhs_c);
479  if( ENTITY_PLUS_P(rhs_op) || ENTITY_PLUS_C_P(rhs_op) ||
480  ENTITY_MINUS_P(rhs_op) || ENTITY_MINUS_C_P(rhs_op) )
481  {
482  expression rhs_rhs = EXPRESSION(CAR(rhs_args));
483  expression rhs_lhs = EXPRESSION(CAR(CDR(rhs_args)));
488  )
489  {
490  return e;
491  }
492  }
493  }
494  }
495  }
496  }
497  }
498  return expression_undefined;
499 }
500 
501 
502 /**
503  * iterate over @param incr, a comma separated expression and checks for an (in|de)crement
504  * of @param loop_index
505  * if @param loop_index is written twice in @param incr , the result is expression_undefined
506  *
507  * @return expression_undefined if no (in|de) crement was found, the *crementing expression otherwise
508  */
509 static
512 {
513  if(expression_call_p(incr))
514  {
515  call c =expression_call(incr);
516  list args = call_arguments(c);
517  entity op = call_function(c);
518  if(ENTITY_COMMA_P(op))
519  {
520  // FI: Serge, why don't you loop over args? O(N^2)...
521  expression rhs = EXPRESSION(CAR(args));
522  expression lhs = EXPRESSION(CAR(CDR(args)));
523 
524  expression lhs_guessed = guess_loop_increment(lhs,loop_index,body);
526  return lhs_guessed;
527 
528  expression rhs_guessed = guess_loop_increment(rhs,loop_index,body);
530  return rhs_guessed;
531  }
532  return guess_loop_increment_walker(incr,loop_index,body);
533  }
534  return expression_undefined;
535 }
536 
537 /**
538  * iterate over the comma-separeted expression @param init
539  * and look for an initialization of @param loop_index
540  *
541  * @return expression_undefined if none found, the initialization expression otherwise
542  */
543 static
546 {
548  {
550  list args = call_arguments(c);
551  entity op = call_function(c);
552  if(ENTITY_COMMA_P(op))
553  {
554  expression rhs = EXPRESSION(CAR(args));
555  expression lhs = EXPRESSION(CAR(CDR(args)));
556 
558  if(expression_undefined_p(guessed))
560  return guessed;
561  }
562  else if(ENTITY_ASSIGN_P(op))
563  {
565  if(expression_reference_p(lhs) &&
567  return init;
568  }
569  }
570  return expression_undefined;
571 }
572 
573 /**
574  * given an expression @param seed that can be found in @param comma_list
575  * iterate over @param comma_list and remove @param seed from the list, updating pointers properly
576  *
577  */
578 static
579 void
581 {
582  if(expression_call_p(comma_list))
583  {
584  call c =expression_call(comma_list);
585  list args = call_arguments(c);
586  entity op = call_function(c);
587  if(ENTITY_COMMA_P(op))
588  {
589  expression rhs = EXPRESSION(CAR(args));
590  expression lhs = EXPRESSION(CAR(CDR(args)));
591  if( lhs == seed ) {
592  expression_syntax(comma_list)=expression_syntax(rhs);
594  }
595  else if(rhs==seed ) {
596  expression_syntax(comma_list)=expression_syntax(lhs);
598  }
599  else {
602  }
603  }
604  }
605 }
606 
607 /* Try to convert a C-like for-loop into a Fortran-like do-loop.
608 
609  Assume to match what is done in the prettyprinter C_loop_range().
610 
611  @return a sequence containing the do-loop if the transformation worked or sequence_undefined if
612  it failed.
613 */
615 {
616 
617  sequence output = sequence_undefined;
619  expression cond = forloop_condition(theloop);
620  expression incr = forloop_increment(theloop);
621  statement body = forloop_body(theloop);
622 
623  set cond_entities = get_referenced_entities(cond);
624  /* This does not filter scalar integers... */
625  set incr_entities = get_referenced_entities(incr);
626  set cond_inter_incr_entities = set_make(set_pointer);
627  cond_inter_incr_entities = set_intersection(cond_inter_incr_entities,incr_entities,cond_entities);
628 
629  SET_FOREACH(entity,loop_index,cond_inter_incr_entities)
630  {
631  /* Consider only scalar integer variables as loop indices */
633  if(scalar_integer_type_p(lit) /* && type_depth(lit)==1*/ ) {
636  {
637  bool is_upper_p,is_increasing_p;
638  expression upper_bound;
639  if(condition_expression_to_final_bound(cond,loop_index,&is_upper_p, &upper_bound))
640  {
641  set upper_bound_entities = get_referenced_entities(upper_bound);
642  bool upper_bound_entity_written=false;
643  SET_FOREACH(entity,e,upper_bound_entities)
644  {
646  {
647  upper_bound_entity_written=true;
648  break;
649  }
650  }
651  set_free(upper_bound_entities);
652  if(!upper_bound_entity_written){
653  /* We got a candidate loop index and final bound,
654  let's check the increment */
655  expression increment_expression =
656  guess_loop_increment(incr,loop_index,body);
657  expression increment;
658  if( !expression_undefined_p(increment_expression) &&
659  incrementation_expression_to_increment(increment_expression,
660  loop_index,
661  &is_increasing_p,
662  &increment))
663  {
664  /* We have found a do-loop compatible for-loop: */
665  output=make_sequence(NIL);
666  if(increment_expression!=incr){
667  remove_expression_from_comma_list(incr,increment_expression);
669  //statement_consistent_p(body);
670  }
671 
672  /* guess lower bound */
674  if(expression_undefined_p(lower_bound))
675  lower_bound=entity_to_expression(loop_index);
676  else {
677  if( lower_bound!= init) {
681  }
682  lower_bound=EXPRESSION(CAR(CDR(call_arguments(expression_call(lower_bound)))));
683  }
684 
685  if (!is_upper_p && is_increasing_p)
686  pips_user_warning("Loop with lower bound and increasing index %s\n", entity_local_name(loop_index));
687  if (is_upper_p && !is_increasing_p)
688  pips_user_warning("Loop with upper bound and decreasing index %s\n", entity_local_name(loop_index));
689 
690  range lr;
691  if(is_upper_p)
692  lr = make_range(lower_bound, upper_bound, increment);
693  else {
694  // FI: Unfortunately, the problem must be
695  // postponed to the prettyprinter
696  lr = make_range(lower_bound, upper_bound, increment);
697  }
698  loop l = make_loop(loop_index, lr, body, statement_label(parent),
700 
701  /* try hard to reproduce statement content */
703  statement_label(parent),
704  statement_number(parent),
706  statement_comments(parent),
708  statement_declarations(parent),
709  statement_decls_text(parent),
711 
716  statement_declarations(parent)=NIL;
717  statement_decls_text(parent)=NULL;
719 
721 
722  }
723  }
724  }
725  }
726  }
727  }
728  set_free(cond_entities);
729  set_free(incr_entities );
730  set_free( cond_inter_incr_entities);
731  return output;
732 }
733 
734 
735 /* Try to to transform the C-like for-loops into Fortran-like do-loops.
736 
737  Assume we are in a gen_recurse since we use gen_get_recurse_ancestor(f).
738  */
739 void
741 
742  /* Get the englobing statement of the "for" assuming we are called
743  from a gen_recurse()-like function: */
744  statement parent=
747 
748  sequence new_l = for_to_do_loop_conversion(f,parent);
749 
750  if (!sequence_undefined_p(new_l)) {
751  pips_debug(3, "do-loop has been generated.\n");
757  free_forloop(f);
758  }
759 }
760 
761 
762 /* For-loop to do-loop transformation phase.
763 
764  This transformation transform for example a
765 \begin{lstlisting}
766 for (i = lb; i < ub; i += stride)
767  body;
768 \end{lstlisting}
769  into a
770 \begin{lstlisting}[language=fortran]
771 do i = lb, ub - 1, stride
772  body
773 end do
774 \end{lstlisting}
775 
776  Now use pure local analysis on the code but we could imagine further
777  use of semantics analysis some day...
778 */
779 bool for_loop_to_do_loop(const string module_name) {
781 
782  /* Get the true ressource, not a copy, since we modify it in place. */
784  (statement) db_get_memory_resource(DBR_CODE, module_name, true);
785 
789 
790  debug_on("FOR_LOOP_TO_DO_LOOP_DEBUG_LEVEL");
791  pips_assert("Statement should be OK before...", statement_consistent_p(module_statement));
792 
793  /* We need to access to the instruction containing the current
794  for-loops, so ask NewGen gen_recurse to keep this informations for
795  us: */
796  /* Iterate on all the for-loops: */
798  // Since for-loop statements can be nested, only restructure in
799  // a bottom-up way, :
801 
802  pips_assert("Statement should be OK after...", statement_consistent_p(module_statement));
803 
804  pips_debug(2, "done\n");
805 
806  debug_off();
807 
808  /* Reorder the module, because some statements have been replaced. */
810 
812 
815 
816  /* Should have worked: */
817  return true;
818 }
819 
820 
821 /** Build a sequence with a while-loop from for-loop parameters.
822 
823  The API is a little weird to comply with the controlizer
824  implementation...
825 */
827  expression cond,
828  expression incr,
829  statement body,
830  extensions exts) {
831  pips_debug(5, "Begin\n");
832 
834  statement incr_st = make_expression_statement(incr);
836 
837  /* Build the loop body of the while with { body; incr_st; } : */
839  incr_st,
840  NULL);
841  /* Build the while(cond) { n_body } statement: */
842  statement wl_st = make_whileloop_statement(cond,
843  n_body,
845  true);
846  if(!empty_extensions_p(exts)) {
849  }
850 
851  /* ifdebug(5) { */
852  /* pips_debug(5, "Initialization statement:\n"); */
853  /* print_statement(init_st); */
854  /* pips_debug(5, "Incrementation statement:\n"); */
855  /* print_statement(incr_st); */
856  /* pips_debug(5, "New body statement with incrementation:\n"); */
857  /* print_statement(n_body); */
858  /* pips_debug(5, "New whileloop statement:\n"); */
859  /* print_statement(wl_st); */
860  /* } */
861 
862  wlseq = make_sequence(CONS(STATEMENT, init_st,
863  CONS(STATEMENT, wl_st, NIL)));
864  return wlseq;
865 }
866 
867 
868 /* Try to to transform the C-like for-loops into Fortran-like do-loops.
869 
870  Assume we are in a gen_recurse since we use gen_get_recurse_ancestor(f).
871 
872  The forloop is freed and replaced by a while loop in the statement
873  owning the for-loop
874  */
875 void
877  pips_debug(5, "Begin\n");
878 
879  /* Get the instruction owning the forloop: */
881  /* Get the statement owning instruction owning the forloop: */
883 
884  /* Get a sequence with a while-loop instead: */
888  forloop_body(f),
890 
891  /* These fields have been re-used, so protect them from memory
892  recycling: */
897 
898  /* We need to replace the for-loop instruction by the sequence
899  instruction. The cleaner way should be to delete the first one and
900  make the other one, but since we are in a gen_recurse() and we
901  iterate on the first one, it is dangerous. Well, I've tried and it
902  works, but valgrind complains a bit. :-)
903 
904  So change the type of the instruction on the fly instead: */
906  instruction_sequence(i) = wls;
907  /* And discard the old for: */
908  free_forloop(f);
909 
910  /* Since we have replaced a statement that may have comments and labels
911  by a sequence, do not forget to forward them where they can be: */
912  /* FI: one issue: st is an ancestor of the current object and some
913  of its pointers are going to be modified although they are being
914  processed by gen_recurse()... */
916 
917  /* Removed useless instructions that may remain: */
918  clean_up_sequences(st);
919 
920  /* ifdebug(5) { */
921  /* print_statement(st); */
922  /* pips_debug(5, "Exiting with statement\n"); */
923  /* } */
924 }
925 
926 /* Same as above, but with no calls to ancestors */
927 void
929  if(forloop_statement_p(st)) {
930  pips_debug(5, "Begin\n");
931 
932  /* Get the instruction owning the forloop: */
933  //instruction i = (instruction) gen_get_recurse_ancestor(f);
935  /* Get the statement owning instruction owning the forloop: */
936  //statement st = (statement) gen_get_recurse_ancestor(i);
938 
939  /* Get a sequence with a while-loop instead: */
943  forloop_body(f),
945 
946  /* These fields have been re-used, so protect them from memory
947  recycling: */
952 
953  /* We need to replace the for-loop instruction by the sequence
954  instruction. The cleaner way should be to delete the first one and
955  make the other one, but since we are in a gen_recurse() and we
956  iterate on the first one, it is dangerous. Well, I've tried and it
957  works, but valgrind complains a bit. :-)
958 
959  So change the type of the instruction on the fly instead: */
961  instruction_sequence(i) = wls;
962  /* And discard the old for: */
963  free_forloop(f);
964 
965  /* Since we have replaced a statement that may have comments and labels
966  by a sequence, do not forget to forward them where they can be: */
967  /* FI: one issue: st is an ancestor of the current object and some
968  of its pointers are going to be modified although they are being
969  processed by gen_recurse()... */
971 
972  /* Removed useless instructions that may remain: */
973  clean_up_sequences(st);
974 
975  /* ifdebug(5) { */
976  /* print_statement(st); */
977  /* pips_debug(5, "Exiting with statement\n"); */
978  /* } */
979  }
980 }
981 
982 
983 /* For-loop to while-loop transformation phase.
984 
985  This transformation transforms a
986 \begin{lstlisting}
987 for (init; cond; update)
988  body;
989 \end{lstlisting}
990  into a
991 \begin{lstlisting}
992 {
993  init;
994  while(cond) {
995  body;
996  update;
997  }
998 }
999 \end{lstlisting}
1000 */
1003 
1004  /* Get the true ressource, not a copy, since we modify it in place. */
1006  (statement) db_get_memory_resource(DBR_CODE, module_name, true);
1007 
1011 
1012  debug_on("FOR_LOOP_TO_WHILE_LOOP_DEBUG_LEVEL");
1013  pips_assert("Statement should be OK before...", statement_consistent_p(module_statement));
1014 
1015  /* We need to access to the instruction containing the current
1016  for-loops, so ask NewGen gen_recurse to keep this informations for
1017  us: */
1018  /* Iterate on all the for-loops: */
1020  // Since for-loop statements can be nested, only restructure in
1021  // a bottom-up way, :
1022  //forloop_domain, gen_true, transform_a_for_loop_into_a_while_loop);
1024 
1025  pips_assert("Statement should be OK after...", statement_consistent_p(module_statement));
1026 
1027  pips_debug(2, "done\n");
1028 
1029  debug_off();
1030 
1031  /* Reorder the module, because some statements have been replaced. */
1033 
1035 
1038 
1039  /* Should have worked: */
1040  return true;
1041 }
instruction make_instruction_loop(loop _field_)
Definition: ri.c:1175
void free_forloop(forloop p)
Definition: ri.c:992
loop make_loop(entity a1, range a2, statement a3, entity a4, execution a5, list a6)
Definition: ri.c:1301
instruction make_instruction_expression(expression _field_)
Definition: ri.c:1196
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
void free_extensions(extensions p)
Definition: ri.c:950
bool statement_consistent_p(statement p)
Definition: ri.c:2195
execution make_execution_sequential(void)
Definition: ri.c:841
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
instruction make_instruction_sequence(sequence _field_)
Definition: ri.c:1169
instruction make_instruction_call(call _field_)
Definition: ri.c:1184
synchronization make_synchronization_none(void)
Definition: ri.c:2424
sequence make_sequence(list a)
Definition: ri.c:2125
extensions copy_extensions(extensions p)
EXTENSIONS.
Definition: ri.c:947
range make_range(expression a1, expression a2, expression a3)
Definition: ri.c:2041
static statement module_statement
Definition: alias_check.c:125
bool clean_up_sequences(statement s)
Recursively clean up the statement sequences by fusing them if possible and by removing useless one.
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
void transform_a_for_loop_statement_into_a_while_loop(statement st)
Same as above, but with no calls to ancestors.
static bool guess_write_effect_on_entity_stmt_walker(statement st, guesser_param *p)
classical statement walker, gen_recurse does not dive into statement declarations
bool guess_late_read_effect_on_entity(expression init, entity loop_index)
Check comma expressions used for initialization.
static bool incrementation_expression_to_increment(expression incr, entity li, bool *is_increasing_p, expression *pincrement)
bool for_loop_to_do_loop(const string module_name)
For-loop to do-loop transformation phase.
static expression guess_loop_increment_walker(expression e, entity loop_index, statement body)
guess the increment of a loop the condition is: the increment must be a reference that is constant in...
void transform_a_for_loop_into_a_while_loop(forloop f)
Try to to transform the C-like for-loops into Fortran-like do-loops.
sequence for_to_while_loop_conversion(expression init, expression cond, expression incr, statement body, extensions exts)
Build a sequence with a while-loop from for-loop parameters.
sequence for_to_do_loop_conversion(forloop theloop, statement parent)
Try to convert a C-like for-loop into a Fortran-like do-loop.
static expression guess_loop_increment(expression incr, entity loop_index, statement body)
iterate over
static bool guess_write_effect_on_entity_walker(call c, guesser_param *p)
Try hard to guess wether the call.
bool for_loop_to_while_loop(const string module_name)
For-loop to while-loop transformation phase.
static expression guess_loop_lower_bound(expression init, entity loop_index)
iterate over the comma-separeted expression
void try_to_transform_a_for_loop_into_a_do_loop(forloop f)
Try to to transform the C-like for-loops into Fortran-like do-loops.
static bool condition_expression_to_final_bound(expression cond, entity li, bool *is_upper_p, expression *pub)
Some passes to transform for-loops into do-loops or while-loops that may be easier to analyze by PIPS...
static void remove_expression_from_comma_list(expression comma_list, expression seed)
given an expression
static bool guess_write_effect_on_entity(void *exp, entity loop_index)
call guess_write_effect_on_entity_walker on each call of
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
bool success
Definition: gpips-local.h:59
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
statement make_statement_from_statement_varargs_list(statement,...)
Build a statement sequence from a statement NULL-terminated varargs list.
Definition: statement.c:735
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
gen_chunk * gen_get_recurse_ancestor(const void *)
Get the first ancestor object encountered during the recursion for the given object.
Definition: genClib.c:3546
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#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
#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 FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_append(list l1, const list l2)
Definition: list.c:471
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_whileloop_statement(expression, statement, int, bool)
Build a while loop statement.
Definition: statement.c:1150
statement make_expression_statement(expression)
Build a statement from a given expression.
Definition: statement.c:1308
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
bool forloop_statement_p(statement)
Definition: statement.c:209
void fix_sequence_statement_attributes(statement)
Since blocks are not represented in Fortran, they cannot carry a label.
Definition: statement.c:2016
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
string bool_to_string(bool)
Definition: string.c:243
set set_intersection(set, const set, const set)
Definition: set.c:229
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
void set_free(set)
Definition: set.c:332
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
static entity uminus
Definition: optimize.c:447
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define ENTITY_PLUS_UPDATE_P(e)
#define ENTITY_MODULO_UPDATE_P(e)
#define ENTITY_NON_EQUAL_P(e)
#define ENTITY_BITWISE_AND_UPDATE_P(e)
#define ENTITY_ASSIGN_P(e)
#define ENTITY_MINUS_P(e)
#define ENTITY_COMMA_P(e)
#define ENTITY_PLUS_P(e)
#define ENTITY_LESS_THAN_P(e)
#define ENTITY_PRE_DECREMENT_P(e)
#define ENTITY_POST_DECREMENT_P(e)
#define ENTITY_POST_INCREMENT_P(e)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define ENTITY_RIGHT_SHIFT_UPDATE_P(e)
#define ENTITY_PRE_INCREMENT_P(e)
#define ENTITY_BITWISE_OR_UPDATE_P(e)
#define ENTITY_PLUS_C_P(e)
#define ENTITY_GREATER_THAN_P(e)
#define ENTITY_MINUS_C_P(e)
#define UNARY_MINUS_OPERATOR_NAME
#define ENTITY_MULTIPLY_UPDATE_P(e)
#define ENTITY_DIVIDE_UPDATE_P(e)
#define ENTITY_BITWISE_XOR_UPDATE_P(e)
#define ENTITY_ADDRESS_OF_P(e)
#define ENTITY_LESS_OR_EQUAL_P(e)
#define empty_comments
Empty comments (i.e.
#define ENTITY_MINUS_UPDATE_P(e)
#define ENTITY_LEFT_SHIFT_UPDATE_P(e)
#define ENTITY_GREATER_OR_EQUAL_P(e)
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
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
entity entity_empty_label(void)
Definition: entity.c:1105
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
set get_referenced_entities(void *elem)
retrieves the set of entities used in elem beware that this entities may be formal parameters,...
Definition: entity.c:3063
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
bool positive_expression_p(expression e)
Use constants and type information to decide if the value of sigma(e) is always positive,...
Definition: eval.c:826
bool negative_expression_p(expression e)
Use constants and type information to decide if the value of sigma(e) is always negative,...
Definition: eval.c:896
expression expression_verbose_reduction_p_and_return_increment(expression incr, bool filter(expression))
Test if an expression is a verbose reduction of the form : "i = i op v" or "i = v op i".
Definition: expression.c:780
bool extended_integer_constant_expression_p(expression e)
More extensive than next function.
Definition: expression.c:858
bool expression_call_p(expression e)
Definition: expression.c:415
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
call expression_call(expression e)
Definition: expression.c:445
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 add_expression_p(expression e)
Test if an expression is an addition.
Definition: expression.c:986
expression convert_bound_expression(expression e, bool upper_p, bool non_strict_p)
Replace a C expression used as FOR bound by a Fortran DO bound expression, taking into account the C ...
Definition: expression.c:2968
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
bool sub_expression_p(expression e)
Definition: expression.c:991
list expression_to_reference_list(expression e, list lr)
conversion of an expression into a list of references; references are appended to list lr as they are...
Definition: expression.c:1263
bool is_expression_reference_to_entity_p(expression e, entity v)
Test if an expression is a reference to a given variable entity.
Definition: expression.c:541
bool empty_extensions_p(extensions es)
Definition: extension.c:50
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
type ultimate_type(type)
Definition: type.c:3466
bool scalar_integer_type_p(type)
Definition: type.c:3276
#define forloop_domain
newgen_extensions_domain_defined
Definition: ri.h:178
#define value_undefined_p(x)
Definition: ri.h:3017
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference_p(x)
Definition: ri.h:2728
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
#define syntax_reference(x)
Definition: ri.h:2730
#define forloop_initialization(x)
Definition: ri.h:1366
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define forloop_increment(x)
Definition: ri.h:1370
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define syntax_call_p(x)
Definition: ri.h:2734
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define statement_label(x)
Definition: ri.h:2450
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_sequence
Definition: ri.h:1469
#define instruction_tag(x)
Definition: ri.h:1511
#define expression_normalized(x)
Definition: ri.h:1249
#define sequence_statements(x)
Definition: ri.h:2360
#define statement_extensions(x)
Definition: ri.h:2464
struct _newgen_struct_instruction_ * instruction
Definition: ri.h:207
#define instruction_sequence(x)
Definition: ri.h:1514
#define instruction_forloop(x)
Definition: ri.h:1538
#define syntax_call(x)
Definition: ri.h:2736
#define expression_undefined_p(x)
Definition: ri.h:1224
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define statement_decls_text(x)
Definition: ri.h:2462
#define forloop_condition(x)
Definition: ri.h:1368
#define call_arguments(x)
Definition: ri.h:711
#define sequence_undefined
Definition: ri.h:2338
#define entity_type(x)
Definition: ri.h:2792
#define statement_number(x)
Definition: ri.h:2452
#define expression_syntax(x)
Definition: ri.h:1247
#define forloop_body(x)
Definition: ri.h:1372
#define sequence_undefined_p(x)
Definition: ri.h:2339
#define loop_index(x)
Definition: ri.h:1640
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
#define ifdebug(n)
Definition: sg.c:47
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
parameter of effect guesser
bool written
wheter the entity seems written
entity target
entity to find effect on
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207