PIPS
for_to_do_or_while_loops.c File Reference
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "ri-util.h"
#include "control.h"
#include "misc.h"
#include "pipsdbm.h"
#include "resources.h"
+ Include dependency graph for for_to_do_or_while_loops.c:

Go to the source code of this file.

Data Structures

struct  guesser_param
 parameter of effect guesser More...
 

Functions

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. More...
 
static bool incrementation_expression_to_increment (expression incr, entity li, bool *is_increasing_p, expression *pincrement)
 
static bool guess_write_effect_on_entity_walker (call c, guesser_param *p)
 Try hard to guess wether the call. More...
 
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 More...
 
static bool guess_write_effect_on_entity (void *exp, entity loop_index)
 call guess_write_effect_on_entity_walker on each call of More...
 
bool guess_late_read_effect_on_entity (expression init, entity loop_index)
 Check comma expressions used for initialization. More...
 
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 the loop body More...
 
static expression guess_loop_increment (expression incr, entity loop_index, statement body)
 iterate over More...
 
static expression guess_loop_lower_bound (expression init, entity loop_index)
 iterate over the comma-separeted expression More...
 
static void remove_expression_from_comma_list (expression comma_list, expression seed)
 given an expression More...
 
sequence for_to_do_loop_conversion (forloop theloop, statement parent)
 Try to convert a C-like for-loop into a Fortran-like do-loop. More...
 
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. More...
 
bool for_loop_to_do_loop (const string module_name)
 For-loop to do-loop transformation phase. More...
 
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. More...
 
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. More...
 
void transform_a_for_loop_statement_into_a_while_loop (statement st)
 Same as above, but with no calls to ancestors. More...
 
bool for_loop_to_while_loop (const string module_name)
 For-loop to while-loop transformation phase. More...
 

Function Documentation

◆ condition_expression_to_final_bound()

static bool condition_expression_to_final_bound ( expression  cond,
entity  li,
bool is_upper_p,
expression pub 
)
static

Some passes to transform for-loops into do-loops or while-loops that may be easier to analyze by PIPS.

Test if the final value

Parameters
liof a for-loop is static.
Returns
:
  • true if the final value of a for-loop is static
  • pub is the new expression of the final value
  • *is_upper_p is set to true if the final value is upper-bound (index is probably increasing) and to false if the final value is lower-bound (index is probably decreasing)

Depending on cond, the so-called upper bound may end up being a lower bound with a decreasing step loop.

ifdebug(5) {

pips_debug(5, "Begin with expression\n");

print_expression(cond);

}

Five operators are accepted

| ENTITY_NON_EQUAL_P(op)

pips_debug(5, "Static final value found!\n"

"\tEnd with expression:\n");

print_expression(*pub);

Definition at line 57 of file for_to_do_or_while_loops.c.

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 }
bool success
Definition: gpips-local.h:59
#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 pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
string bool_to_string(bool)
Definition: string.c:243
#define ENTITY_NON_EQUAL_P(e)
#define ENTITY_LESS_THAN_P(e)
#define ENTITY_GREATER_THAN_P(e)
#define ENTITY_LESS_OR_EQUAL_P(e)
#define ENTITY_GREATER_OR_EQUAL_P(e)
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
#define syntax_reference_p(x)
Definition: ri.h:2728
#define syntax_reference(x)
Definition: ri.h:2730
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define syntax_call_p(x)
Definition: ri.h:2734
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define syntax_call(x)
Definition: ri.h:2736
#define call_arguments(x)
Definition: ri.h:711
#define expression_syntax(x)
Definition: ri.h:1247
#define ifdebug(n)
Definition: sg.c:47

References bool_to_string(), call_arguments, call_function, CAR, CDR, convert_bound_expression(), ENTITY_GREATER_OR_EQUAL_P, ENTITY_GREATER_THAN_P, ENTITY_LESS_OR_EQUAL_P, ENTITY_LESS_THAN_P, ENTITY_NON_EQUAL_P, EXPRESSION, expression_syntax, ifdebug, pips_debug, reference_variable, syntax_call, syntax_call_p, syntax_reference, and syntax_reference_p.

Referenced by for_to_do_loop_conversion().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ for_loop_to_do_loop()

bool for_loop_to_do_loop ( const string  module_name)

For-loop to do-loop transformation phase.

This transformation transform for example a \begin{lstlisting} for (i = lb; i < ub; i += stride) body; \end{lstlisting} into a \begin{lstlisting}[language=fortran] do i = lb, ub - 1, stride body end do \end{lstlisting}

Now use pure local analysis on the code but we could imagine further use of semantics analysis some day...

Get the true ressource, not a copy, since we modify it in place.

We need to access to the instruction containing the current for-loops, so ask NewGen gen_recurse to keep this informations for us:

Iterate on all the for-loops:

Reorder the module, because some statements have been replaced.

Should have worked:

Parameters
module_nameodule_name

Definition at line 779 of file for_to_do_or_while_loops.c.

779  {
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 }
bool statement_consistent_p(statement p)
Definition: ri.c:2195
static statement module_statement
Definition: alias_check.c:125
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 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.
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
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_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
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
#define debug_on(env)
Definition: misc-local.h:157
#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
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
#define forloop_domain
newgen_extensions_domain_defined
Definition: ri.h:178

References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, forloop_domain, gen_recurse, gen_true(), module_name(), module_name_to_entity(), module_reorder(), module_statement, pips_assert, pips_debug, reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), statement_consistent_p(), and try_to_transform_a_for_loop_into_a_do_loop().

+ Here is the call graph for this function:

◆ for_loop_to_while_loop()

bool for_loop_to_while_loop ( const string  module_name)

For-loop to while-loop transformation phase.

This transformation transforms a \begin{lstlisting} for (init; cond; update) body; \end{lstlisting} into a \begin{lstlisting} { init; while(cond) { body; update; } } \end{lstlisting}

Get the true ressource, not a copy, since we modify it in place.

We need to access to the instruction containing the current for-loops, so ask NewGen gen_recurse to keep this informations for us:

Iterate on all the for-loops:

Reorder the module, because some statements have been replaced.

Should have worked:

Parameters
module_nameodule_name

Definition at line 1001 of file for_to_do_or_while_loops.c.

1001  {
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 }
void transform_a_for_loop_statement_into_a_while_loop(statement st)
Same as above, but with no calls to ancestors.
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362

References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, gen_recurse, gen_true(), module_name(), module_name_to_entity(), module_reorder(), module_statement, pips_assert, pips_debug, reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), statement_consistent_p(), statement_domain, and transform_a_for_loop_statement_into_a_while_loop().

+ Here is the call graph for this function:

◆ for_to_do_loop_conversion()

sequence for_to_do_loop_conversion ( forloop  theloop,
statement  parent 
)

Try to convert a C-like for-loop into a Fortran-like do-loop.

Assume to match what is done in the prettyprinter C_loop_range().

Returns
a sequence containing the do-loop if the transformation worked or sequence_undefined if it failed.

This does not filter scalar integers...

Consider only scalar integer variables as loop indices

&& type_depth(lit)==1

We got a candidate loop index and final bound, let's check the increment

We have found a do-loop compatible for-loop:

guess lower bound

try hard to reproduce statement content

Parameters
theloopheloop
parentarent

Definition at line 614 of file for_to_do_or_while_loops.c.

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 }
instruction make_instruction_loop(loop _field_)
Definition: ri.c:1175
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
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_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
range make_range(expression a1, expression a2, expression a3)
Definition: ri.c:2041
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)
static expression guess_loop_increment(expression incr, entity loop_index, statement body)
iterate over
static expression guess_loop_lower_bound(expression init, entity loop_index)
iterate over the comma-separeted expression
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
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
#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_append(list l1, const list l2)
Definition: list.c:471
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
#define pips_user_warning
Definition: misc-local.h:146
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
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
#define STATEMENT_NUMBER_UNDEFINED
default values
#define empty_comments
Empty comments (i.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
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
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
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_initialization(x)
Definition: ri.h:1366
#define forloop_increment(x)
Definition: ri.h:1370
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_label(x)
Definition: ri.h:2450
#define sequence_statements(x)
Definition: ri.h:2360
#define statement_extensions(x)
Definition: ri.h:2464
#define expression_undefined_p(x)
Definition: ri.h:1224
#define statement_declarations(x)
Definition: ri.h:2460
#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 sequence_undefined
Definition: ri.h:2338
#define entity_type(x)
Definition: ri.h:2792
#define statement_number(x)
Definition: ri.h:2452
#define forloop_body(x)
Definition: ri.h:1372
#define loop_index(x)
Definition: ri.h:1640
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59

References call_arguments, CAR, CDR, condition_expression_to_final_bound(), CONS, empty_comments, empty_extensions(), entity_empty_label(), entity_local_name(), entity_to_expression(), entity_type, EXPRESSION, expression_call(), expression_undefined_p, forloop_body, forloop_condition, forloop_increment, forloop_initialization, gen_append(), get_referenced_entities(), guess_late_read_effect_on_entity(), guess_loop_increment(), guess_loop_lower_bound(), guess_write_effect_on_entity(), incrementation_expression_to_increment(), init, insert_statement(), instruction_to_statement(), loop_index, make_execution_sequential(), make_instruction_call(), make_instruction_expression(), make_instruction_loop(), make_loop(), make_range(), make_sequence(), make_statement(), make_synchronization_none(), NIL, pips_user_warning, remove_expression_from_comma_list(), scalar_integer_type_p(), sequence_statements, sequence_undefined, SET_FOREACH, set_free(), set_intersection(), set_make(), set_pointer, STATEMENT, statement_comments, statement_declarations, statement_decls_text, statement_extensions, statement_label, statement_number, STATEMENT_NUMBER_UNDEFINED, statement_ordering, STATEMENT_ORDERING_UNDEFINED, and ultimate_type().

Referenced by controlize_forloop(), and try_to_transform_a_for_loop_into_a_do_loop().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ for_to_while_loop_conversion()

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.

The API is a little weird to comply with the controlizer implementation...

Build the loop body of the while with { body; incr_st; } :

Build the while(cond) { n_body } statement:

ifdebug(5) {

pips_debug(5, "Initialization statement:\n");

print_statement(init_st);

pips_debug(5, "Incrementation statement:\n");

print_statement(incr_st);

pips_debug(5, "New body statement with incrementation:\n");

print_statement(n_body);

pips_debug(5, "New whileloop statement:\n");

print_statement(wl_st);

}

Parameters
initnit
condond
incrncr
bodyody
extsxts

Definition at line 826 of file for_to_do_or_while_loops.c.

830  {
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 }
void free_extensions(extensions p)
Definition: ri.c:950
extensions copy_extensions(extensions p)
EXTENSIONS.
Definition: ri.c:947
statement make_statement_from_statement_varargs_list(statement,...)
Build a statement sequence from a statement NULL-terminated varargs list.
Definition: statement.c:735
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
bool empty_extensions_p(extensions es)
Definition: extension.c:50

References CONS, copy_extensions(), empty_extensions_p(), free_extensions(), init, make_expression_statement(), make_sequence(), make_statement_from_statement_varargs_list(), make_whileloop_statement(), NIL, pips_debug, sequence_undefined, STATEMENT, statement_extensions, and STATEMENT_NUMBER_UNDEFINED.

Referenced by controlize_forloop(), transform_a_for_loop_into_a_while_loop(), and transform_a_for_loop_statement_into_a_while_loop().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ guess_late_read_effect_on_entity()

bool guess_late_read_effect_on_entity ( expression  init,
entity  loop_index 
)

Check comma expressions used for initialization.

for_to_do_or_while_loops.c

Assuming loop_index is a potential do loop index, and init a comma expression, do we have subexpressions after the loop_index initialization that may use this index? If yes, the loop cannot be transformed into a DO loop, because this subexpression will be moved before the loop index initialization. Or the loop index initialization should be replicated before the loop.

Example (SPEC2006, milc):

for (i = parity==0x01?even_sites_on_node:0, s = &lattice[i]; i<(parity==0x02?even_sites_on_node:sites_on_node); i++, s++) {

s = &lattice[i] is going to be placed ahead of i's own initialization.

In other words, the loop can be changed in different ways:

  • the loop is converted into a while loop with the initialization expression moved into a statement (easy, alreayd implemented, safe)
  • the conversion into a DO loop is performed, but all initializations are moved into a statement and the new initialization expression is "loop_init = loop_init" to satisfy the do loop semantics (a new implementation is required).
Parameters
initnit
loop_indexoop_index

Definition at line 412 of file for_to_do_or_while_loops.c.

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 }
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
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
#define ENTITY_COMMA_P(e)
bool expression_call_p(expression e)
Definition: expression.c:415
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
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References call_arguments, call_function, ENTITY_COMMA_P, EXPRESSION, expression_call(), expression_call_p(), expression_to_reference_list(), f(), FOREACH, gen_free_list(), guess_write_effect_on_entity(), init, loop_index, NIL, REFERENCE, and reference_variable.

Referenced by for_to_do_loop_conversion().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ guess_loop_increment()

static expression guess_loop_increment ( expression  incr,
entity  loop_index,
statement  body 
)
static

iterate over

Parameters
incr,acomma separated expression and checks for an (in|de)crement of
loop_indexif
loop_indexis written twice in
incr,theresult is expression_undefined
Returns
expression_undefined if no (in|de) crement was found, the *crementing expression otherwise

Definition at line 511 of file for_to_do_or_while_loops.c.

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 }
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...
#define expression_undefined
Definition: ri.h:1223

References call_arguments, call_function, CAR, CDR, ENTITY_COMMA_P, EXPRESSION, expression_call(), expression_call_p(), expression_undefined, expression_undefined_p, guess_loop_increment_walker(), guess_write_effect_on_entity(), and loop_index.

Referenced by for_to_do_loop_conversion().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ guess_loop_increment_walker()

static expression guess_loop_increment_walker ( expression  e,
entity  loop_index,
statement  body 
)
static

guess the increment of a loop the condition is: the increment must be a reference that is constant in the loop body

Parameters
ecandidate expression
loop_indexentity guessed as index
bodyloop body
Returns
selected increment expression

this one needs further processing

Definition at line 453 of file for_to_do_or_while_loops.c.

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 }
#define ENTITY_PLUS_UPDATE_P(e)
#define ENTITY_ASSIGN_P(e)
#define ENTITY_MINUS_P(e)
#define ENTITY_PLUS_P(e)
#define ENTITY_PRE_DECREMENT_P(e)
#define ENTITY_POST_DECREMENT_P(e)
#define ENTITY_POST_INCREMENT_P(e)
#define ENTITY_PRE_INCREMENT_P(e)
#define ENTITY_PLUS_C_P(e)
#define ENTITY_MINUS_C_P(e)
#define ENTITY_MINUS_UPDATE_P(e)
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
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

References call_arguments, call_function, CAR, CDR, ENTITY_ASSIGN_P, ENTITY_MINUS_C_P, ENTITY_MINUS_P, ENTITY_MINUS_UPDATE_P, ENTITY_PLUS_C_P, ENTITY_PLUS_P, ENTITY_PLUS_UPDATE_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, EXPRESSION, expression_call(), expression_call_p(), expression_reference(), expression_reference_p(), expression_undefined, guess_write_effect_on_entity(), loop_index, reference_variable, and same_entity_p().

Referenced by guess_loop_increment().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ guess_loop_lower_bound()

static expression guess_loop_lower_bound ( expression  init,
entity  loop_index 
)
static

iterate over the comma-separeted expression

Parameters
initand look for an initialization of
loop_index
Returns
expression_undefined if none found, the initialization expression otherwise

Definition at line 545 of file for_to_do_or_while_loops.c.

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 }

References call_arguments, call_function, CAR, CDR, ENTITY_ASSIGN_P, ENTITY_COMMA_P, EXPRESSION, expression_call(), expression_call_p(), expression_reference(), expression_reference_p(), expression_undefined, expression_undefined_p, init, loop_index, reference_variable, and same_entity_p().

Referenced by for_to_do_loop_conversion().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ guess_write_effect_on_entity()

static bool guess_write_effect_on_entity ( void *  exp,
entity  loop_index 
)
static

call guess_write_effect_on_entity_walker on each call of

Parameters
expin order to guess write effect on
loop_index
Returns
true if we are sure the entity was written, false otherwise, let's be optimistic :)

Definition at line 372 of file for_to_do_or_while_loops.c.

373 {
374  guesser_param p = { loop_index, false };
378  0);
379  return p.written;
380 
381 
382 }
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
static bool guess_write_effect_on_entity_walker(call c, guesser_param *p)
Try hard to guess wether the call.
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
parameter of effect guesser
bool written
wheter the entity seems written
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207

References call_domain, exp, gen_context_multi_recurse(), gen_null(), guess_write_effect_on_entity_stmt_walker(), guess_write_effect_on_entity_walker(), loop_index, statement_domain, and guesser_param::written.

Referenced by for_to_do_loop_conversion(), guess_late_read_effect_on_entity(), guess_loop_increment(), and guess_loop_increment_walker().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ guess_write_effect_on_entity_stmt_walker()

static bool guess_write_effect_on_entity_stmt_walker ( statement  st,
guesser_param p 
)
static

classical statement walker, gen_recurse does not dive into statement declarations

Definition at line 357 of file for_to_do_or_while_loops.c.

358 {
360  if( !value_undefined_p(entity_initial(e) ) ) {
362  }
363  return true;
364 }
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
#define value_undefined_p(x)
Definition: ri.h:3017
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define entity_initial(x)
Definition: ri.h:2796

References call_domain, ENTITY, entity_initial, FOREACH, gen_context_recurse, gen_null2(), guess_write_effect_on_entity_walker(), statement_declarations, and value_undefined_p.

Referenced by guess_write_effect_on_entity().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ guess_write_effect_on_entity_walker()

static bool guess_write_effect_on_entity_walker ( call  c,
guesser_param p 
)
static

Try hard to guess wether the call.

Parameters
cwrites
pNote that it is just a guess and may be wwrong

This function only exists because effects are not available in the controlizer moreover, no aliasing information is available, so the guess may be wrong

Definition at line 329 of file for_to_do_or_while_loops.c.

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 }
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
#define ENTITY_MODULO_UPDATE_P(e)
#define ENTITY_BITWISE_AND_UPDATE_P(e)
#define ENTITY_RIGHT_SHIFT_UPDATE_P(e)
#define ENTITY_BITWISE_OR_UPDATE_P(e)
#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_LEFT_SHIFT_UPDATE_P(e)
entity target
entity to find effect on

References call_arguments, call_function, CAR, ENTITY_ADDRESS_OF_P, ENTITY_ASSIGN_P, ENTITY_BITWISE_AND_UPDATE_P, ENTITY_BITWISE_OR_UPDATE_P, ENTITY_BITWISE_XOR_UPDATE_P, ENTITY_DIVIDE_UPDATE_P, ENTITY_LEFT_SHIFT_UPDATE_P, ENTITY_MINUS_UPDATE_P, ENTITY_MODULO_UPDATE_P, ENTITY_MULTIPLY_UPDATE_P, ENTITY_PLUS_UPDATE_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, ENTITY_RIGHT_SHIFT_UPDATE_P, EXPRESSION, expression_reference(), expression_reference_p(), gen_recurse_stop(), reference_variable, same_entity_p(), guesser_param::target, and guesser_param::written.

Referenced by guess_write_effect_on_entity(), and guess_write_effect_on_entity_stmt_walker().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ incrementation_expression_to_increment()

static bool incrementation_expression_to_increment ( expression  incr,
entity  li,
bool is_increasing_p,
expression pincrement 
)
static

The expression should concern the loop index:

Look for i++ or ++i:

Look for i– or –i:

Look for stuff like "i += integer". Get the rhs:

This fails with floating point indices as found in industrial code and with symbolic increments as in "for(t=0.0; t<t_max; t += delta_t). Floating point indices should be taken into account. The iteration direction of the loop should be derived from the bound expression, using the comparison operator.

SG: we checked the no-write-effect-on-increment earlier, we can go on safely, but we will not know if the increment is positive or not, assume yes ?

Look for "i = i + v" (only for v positive here...) or "i = v + i":

SG: we checked the no-write-effect-on-increment earlier, we can go on safely, but we will not know if the increment is positive or not, assume yes ?

SG: i am duplicating code, next generation of phd will clean it

SG: we checked the no-write-effect-on-increment earlier, we can go on safely, but we will not know if the increment is positive or not, assume yes ?

Definition at line 141 of file for_to_do_or_while_loops.c.

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 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
static entity uminus
Definition: optimize.c:447
#define UNARY_MINUS_OPERATOR_NAME
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
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
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 MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
bool sub_expression_p(expression e)
Definition: expression.c:991
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

References add_expression_p(), call_arguments, call_function, CAR, CDR, copy_expression(), ENDP, entity_intrinsic(), ENTITY_MINUS_UPDATE_P, ENTITY_PLUS_UPDATE_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, EXPRESSION, expression_constant_p(), expression_syntax, expression_to_int(), expression_undefined, expression_verbose_reduction_p_and_return_increment(), extended_integer_constant_expression_p(), int_to_expression(), is_expression_reference_to_entity_p(), MakeUnaryCall(), negative_expression_p(), pips_debug, positive_expression_p(), sub_expression_p(), syntax_call, syntax_call_p, uminus, and UNARY_MINUS_OPERATOR_NAME.

Referenced by for_to_do_loop_conversion().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_expression_from_comma_list()

static void remove_expression_from_comma_list ( expression  comma_list,
expression  seed 
)
static

given an expression

Parameters
seedthat can be found in
comma_listiterate over
comma_listand remove
seedfrom the list, updating pointers properly

Definition at line 580 of file for_to_do_or_while_loops.c.

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 }
#define normalized_undefined
Definition: ri.h:1745
#define expression_normalized(x)
Definition: ri.h:1249

References call_arguments, call_function, CAR, CDR, ENTITY_COMMA_P, EXPRESSION, expression_call(), expression_call_p(), expression_normalized, expression_syntax, and normalized_undefined.

Referenced by for_to_do_loop_conversion().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transform_a_for_loop_into_a_while_loop()

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.

Assume we are in a gen_recurse since we use gen_get_recurse_ancestor(f).

The forloop is freed and replaced by a while loop in the statement owning the for-loop

Get the instruction owning the forloop:

Get the statement owning instruction owning the forloop:

Get a sequence with a while-loop instead:

These fields have been re-used, so protect them from memory recycling:

We need to replace the for-loop instruction by the sequence instruction. The cleaner way should be to delete the first one and make the other one, but since we are in a gen_recurse() and we iterate on the first one, it is dangerous. Well, I've tried and it works, but valgrind complains a bit. :-)

So change the type of the instruction on the fly instead:

And discard the old for:

Since we have replaced a statement that may have comments and labels by a sequence, do not forget to forward them where they can be:

FI: one issue: st is an ancestor of the current object and some of its pointers are going to be modified although they are being processed by gen_recurse()...

Removed useless instructions that may remain:

ifdebug(5) {

print_statement(st);

pips_debug(5, "Exiting with statement\n");

}

Definition at line 876 of file for_to_do_or_while_loops.c.

876  {
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 }
void free_forloop(forloop p)
Definition: ri.c:992
bool clean_up_sequences(statement s)
Recursively clean up the statement sequences by fusing them if possible and by removing useless one.
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.
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 fix_sequence_statement_attributes(statement)
Since blocks are not represented in Fortran, they cannot carry a label.
Definition: statement.c:2016
@ is_instruction_sequence
Definition: ri.h:1469
#define instruction_tag(x)
Definition: ri.h:1511
struct _newgen_struct_instruction_ * instruction
Definition: ri.h:207
#define instruction_sequence(x)
Definition: ri.h:1514
#define statement_undefined
Definition: ri.h:2419

References clean_up_sequences(), expression_undefined, f(), fix_sequence_statement_attributes(), for_to_while_loop_conversion(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_forloop(), gen_get_recurse_ancestor(), instruction_sequence, instruction_tag, is_instruction_sequence, pips_debug, statement_extensions, and statement_undefined.

+ Here is the call graph for this function:

◆ transform_a_for_loop_statement_into_a_while_loop()

void transform_a_for_loop_statement_into_a_while_loop ( statement  st)

Same as above, but with no calls to ancestors.

Get the instruction owning the forloop:

Get the statement owning instruction owning the forloop:

Get a sequence with a while-loop instead:

These fields have been re-used, so protect them from memory recycling:

We need to replace the for-loop instruction by the sequence instruction. The cleaner way should be to delete the first one and make the other one, but since we are in a gen_recurse() and we iterate on the first one, it is dangerous. Well, I've tried and it works, but valgrind complains a bit. :-)

So change the type of the instruction on the fly instead:

And discard the old for:

Since we have replaced a statement that may have comments and labels by a sequence, do not forget to forward them where they can be:

FI: one issue: st is an ancestor of the current object and some of its pointers are going to be modified although they are being processed by gen_recurse()...

Removed useless instructions that may remain:

ifdebug(5) {

print_statement(st);

pips_debug(5, "Exiting with statement\n");

}

Parameters
stt

Definition at line 928 of file for_to_do_or_while_loops.c.

928  {
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 }
bool forloop_statement_p(statement)
Definition: statement.c:209
#define instruction_forloop(x)
Definition: ri.h:1538
#define statement_instruction(x)
Definition: ri.h:2458

References clean_up_sequences(), expression_undefined, f(), fix_sequence_statement_attributes(), for_to_while_loop_conversion(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, forloop_statement_p(), free_forloop(), instruction_forloop, instruction_sequence, instruction_tag, is_instruction_sequence, pips_debug, statement_extensions, statement_instruction, and statement_undefined.

Referenced by for_loop_to_while_loop(), and new_controlizer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ try_to_transform_a_for_loop_into_a_do_loop()

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.

Assume we are in a gen_recurse since we use gen_get_recurse_ancestor(f).

Get the englobing statement of the "for" assuming we are called from a gen_recurse()-like function:

Definition at line 740 of file for_to_do_or_while_loops.c.

740  {
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 }
instruction make_instruction_sequence(sequence _field_)
Definition: ri.c:1169
sequence for_to_do_loop_conversion(forloop theloop, statement parent)
Try to convert a C-like for-loop into a Fortran-like do-loop.
#define sequence_undefined_p(x)
Definition: ri.h:2339

References expression_undefined, f(), for_to_do_loop_conversion(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_forloop(), gen_get_recurse_ancestor(), make_instruction_sequence(), pips_debug, sequence_undefined_p, statement_instruction, and statement_undefined.

Referenced by for_loop_to_do_loop(), and new_controlizer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: