PIPS
delay.c
Go to the documentation of this file.
1 /*
2 
3  $Id: delay.c 23644 2021-03-10 09:44:25Z 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 
25 /**
26 * @file delay.c
27 *
28 * @author Serge Guelton <serge.guelton@enst-bretagne.fr>
29 * @version
30 * @date 2010-12-15
31 *
32 * Implementation of inter procedural load / store delaying
33 *
34 */
35 
36 #ifdef HAVE_CONFIG_H
37  #include "pips_config.h"
38 #endif
39 
40 #include "genC.h"
41 #include "linear.h"
42 #include "ri.h"
43 #include "effects.h"
44 
45 #include "resources.h"
46 
47 #include "misc.h"
48 #include "ri-util.h"
49 #include "workspace-util.h"
50 #include "effects-util.h"
51 #include "pipsdbm.h"
52 #include "preprocessor.h"
53 
54 #include "effects-generic.h"
55 #include "effects-convex.h"
56 #include "properties.h"
57 
58 #include "callgraph.h"
59 #include "transformations.h"
60 
61 #include "dg.h"
62 
65 
66 #include "graph.h"
67 #include "control.h"
68 
69 #include "ricedg.h"
70 #include "effects-simple.h"
71 #include "accel-util.h"
72 
74 
75 /* helper to transform preferences in references */
76 static bool do_remove_preference(cell c){
77  if(cell_preference_p(c)) {
80  );
83  cell_reference(c)=r;
84  }
85  return true;
86 }
87 
88 /* entry point to transform preferences in references */
89 void remove_preferences(void * obj) {
91 }
92 
94 
95 static bool simd_load_call_p(call c) {
96  const char* funcName = entity_local_name(call_function(c));
97  const char* simd= get_string_property("ACCEL_LOAD");
98  return same_stringn_p(funcName, simd, strlen(simd));
99 }
100 static bool simd_work_call_p(call c) {
101  const char* funcName = entity_local_name(call_function(c));
102  const char* simd= get_string_property("ACCEL_WORK");
103  return same_stringn_p(funcName, simd, strlen(simd));
104 }
105 static bool simd_store_call_p(call c) {
106  const char* funcName = entity_local_name(call_function(c));
107  const char* simd= get_string_property("ACCEL_STORE");
108  return same_stringn_p(funcName, simd, strlen(simd));
109 }
110 
112 {
113  return statement_call_p(stat) && simd_load_call_p(statement_call(stat));
114 }
116 {
117  return statement_call_p(stat) && simd_work_call_p(statement_call(stat));
118 }
120 {
121  return statement_call_p(stat) && simd_store_call_p(statement_call(stat));
122 }
123 
124 /* This function returns true if the statement is a simd loadsave
125  * statement
126  */
128 {
129  return simd_load_stat_p(stat) || simd_store_stat_p(stat);
130 }
131 
132 /* This function returns true if the statement is a simd
133  * statement
134  */
136 {
137  return simd_dma_stat_p(stat) || simd_work_stat_p(stat);
138 }
139 
140 
141 
142 static bool dma_conflict_p(conflict c)
143 {
144  effect source = conflict_source(c),
145  sink = conflict_sink(c);
146  descriptor dsource = effect_descriptor(source),
147  dsink = effect_descriptor(sink);
148  if(descriptor_convex_p(dsource) && descriptor_convex_p(dsink))
149  {
150  Psysteme psource = descriptor_convex(dsource),
151  psink = descriptor_convex(dsink);
152  return !(sc_inclusion_p(psink,psource) || sc_inclusion_p(psource,psink));
153  }
154  /* be conservative */
155  return true;
156 }
157 
158 /* checks if there exist a conflict between @p s0 and @p s1
159  * according to the dependency graph
160  */
162  /* in intra procedural, a store always conflicts with a return */
164  ( simd_store_stat_p(s0) || simd_store_stat_p(s1) ) &&
166  return true;
167 
168  /* special hook for loop statements: dependency on the index are not well generated */
169  if(statement_loop_p(s1)) {
171  set re = get_referenced_entities(s0);
172  bool conflict = set_belong_p(re,index);
173  set_free(re);
174  return conflict;
175  }
176 
183  return true;
184  }
185  }
186  }
187  }
188  return false;
189 }
190 /* same as statements_conflict_p but W-* conflicts are ignored if load_p,
191  * R-* conflicts are ignored if not load_p */
192 static bool statements_conflict_relaxed_p(statement s0, statement s1, bool load_p) {
193  /* in intra procedural, a store always conflicts with a return */
195  ( simd_store_stat_p(s0) || simd_store_stat_p(s1) ) &&
197  return true;
198 
201  if(statement_ordering(s) == statement_ordering(s0) ) {
202  intptr_t expected = statement_ordering(s1) ;
206  if( (load_p && !effect_write_p(conflict_source(c))) ||
207  (!load_p && !effect_read_p(conflict_source(c))) )
208  return true;
209  }
210  }
211  }
212  }
213  }
214  return false;
215 }
224  if(dma_conflict_p(c)) return true;
225  }
226  }
227  }
228  }
229  return false;
230 }
231 
232 /* helper for do_recurse_statements_conflict_p */
233 typedef struct {
235  bool conflict;
236 } conflict_t;
237 
238 /* helper for recurse_statements_conflict_p */
243  gen_recurse_stop(0);
244 }
245 
246 /* checks if there is a conflict between @p s and any statement in @p in */
248  conflict_t c = { s, false };
250  return c.conflict;
251 }
252 
253 typedef struct {
254  bool result;
256  bool backward;
260 } context;
261 
263  // FI: Missing initializer... I add statement_undefined...
265  return cp;
266 }
267 
269 
271  pips_assert("true", block==block);
273  if(c->backward) stats=gen_nreverse(stats); //reverse the walking when performing backward movements
274  FOREACH(STATEMENT,st,stats) {
276  }
277  gen_free_list(stats);
278 }
280  if(!statement_block_p(*s) && !*block) {
281  pips_assert("declaration must be in a block\n",!declaration_statement_p(*s));
284  list tmp = CONS(STATEMENT,scopy,NIL);
287  *s=scopy;
288 
289  }
290 }
291 
292 static void insert_statement_in_block(statement s, statement inserted, bool before, list *block) {
293  if(statement_block_p(s))
294  insert_statement(s,inserted,before);
295  else {
297  if(before)
298  *block=gen_insert_before(inserted,s,*block);
299  else
300  gen_insert_after(inserted,s,*block);
301  }
302 }
303 
304 static void manage_conflicts(statement s, context *c,bool before, list *block) {
305  /* check conflicts with current stats */
306  list tstats = gen_copy_seq(c->stats);
307  FOREACH(STATEMENT,st,tstats) {
308  if(statements_conflict_p(s,st)) {
309  insert_statement_in_block(s,st,before,block);
310  gen_remove_once(&c->stats,st);
311  }
312  }
313  gen_free_list(tstats);
314 }
315 
318  /* memorize additional dma */
319  if( (c->backward && simd_load_stat_p(s)) ||
320  (!c->backward && simd_store_stat_p(s)) ) {
324  statement_ordering(s)=o;
329  }
330 }
331 
333  manage_conflicts(s,c,!c->backward, block);
334  /* explore both branches independently */
335  test t = statement_test(s);
336  context c0 = context_dup(c), c1=context_dup(c);
339  /* manage state consistency after s :
340  * currently very pessimistic: if a dma is made on a branch, it must be
341  * done at the end of the branch.
342  * A more elaborated version could be to check that same pointers are stored
343  * and that they can be merged later ...
344  */
345  list tstats = gen_copy_seq(c0.stats);
346  FOREACH(STATEMENT,st0,tstats) {
347  intptr_t o = statement_ordering(st0);
348  bool new = true;
349  FOREACH(STATEMENT,st,c->stats) {
350  if(statement_ordering(st) == o ) {
351  new=false;
352  break;
353  }
354  }
355  if(new) {
357  gen_remove_once(&c0.stats,st0);
358  gen_remove_once(&c->stats,st0);
359  }
360  }
361  gen_free_list(tstats);
362  /* the same for the false branch */
363  tstats = gen_copy_seq(c1.stats);
364  FOREACH(STATEMENT,st1,tstats) {
365  intptr_t o = statement_ordering(st1);
366  bool new = true;
367  FOREACH(STATEMENT,st,c->stats) {
368  if(statement_ordering(st) == o ) {
369  new=false;
370  break;
371  }
372  }
373  if(new) {
375  gen_remove_once(&c1.stats,st1);
376  gen_remove_once(&c->stats,st1);
377  }
378  }
379  gen_free_list(tstats);
380  /* now we have the opposite case: a dma was made on a branch
381  * but not on the other one,
382  * in that case we must do it at the end of the other branch
383  */
384  tstats = gen_copy_seq(c->stats);
385  FOREACH(STATEMENT,st,tstats) {
387  /* true branch */
388  bool tfound =false,ffound=false;
389  FOREACH(STATEMENT,st0,c0.stats)
390  if((tfound= (o == statement_ordering(st0)))) break;
391  /* false branch */
392  FOREACH(STATEMENT,st1,c1.stats)
393  if((ffound= (o == statement_ordering(st1)))) break;
394  /* insert it if it's missing somewhere */
395  if(tfound && !ffound ) {
397  gen_remove_once(&c->stats,st);
398  }
399  if(!tfound && ffound ) {
401  gen_remove_once(&c->stats,st);
402  }
403  }
404  gen_free_list(tstats);
405 }
406 
409  if(statement_loop_p(s)) body =loop_body(statement_loop(s));
410  else if(statement_forloop_p(s)) body =forloop_body(statement_forloop(s));
412  pips_assert("all loops have body\n",!statement_undefined_p(s));
413 
414  /* first step is to check conflict with the head */
416  /* then we check if there is a conflict inside the loop.
417  * In that case better insert before the loop than inside */
418  list tstats = gen_copy_seq(c->stats);
419  FOREACH(STATEMENT,st,tstats) {
420  if(recurse_statements_conflict_p(st,body) ) { // conflict with other iterations
422  gen_remove_once(&c->stats,st);
423  }
424  }
425  gen_free_list(tstats);
426 
427  /* then we propagate the dma inside the body */
428  context cb = context_dup(c);
429  delay_communications_statement(body,c,NULL);
430 
431 
432  /* then we check for conflicts with indices or over iterations */
433  tstats = gen_copy_seq(c->stats);
434  FOREACH(STATEMENT,st,tstats) {
435  if(statements_conflict_p(st,s) ||// conflict with the iteration
436  recurse_statements_conflict_p(st,body) ) { // conflict with other iterations
437  insert_statement_in_block(body,st,c->backward,NULL);
438  gen_remove_once(&c->stats,st);
439  }
440  }
441  gen_free_list(tstats);
442  /* if statements have been moved outside the loop
443  * then we (may) need to flatten
444  */
445  FOREACH(STATEMENT,st,c->stats) {
447  c->need_flatten|=true;
448  break;
449  }
450  }
451  gen_free_list(cb.stats);
452 
453 }
454 
457  switch(instruction_tag(i)) {
458  case is_instruction_expression:/* we could do better */
459  case is_instruction_call:
460  delay_communications_call(s,c,block);break;
463  case is_instruction_test:
464  delay_communications_test(s,c,NULL);break;
465  case is_instruction_loop:
468  delay_communications_anyloop(s,c,NULL);break;
469  default:
470  pips_user_warning("not implemented yet, full memory barrier is assumed\n");
471  {
472  list tstats= gen_copy_seq(c->stats);
473  FOREACH(STATEMENT,st,tstats) {
475  gen_remove_once(&c->stats,st);
476  }
477  gen_free_list(tstats);
478  }
479 
480  };
481  pips_assert("everything is ok",statement_consistent_p(s));
482 }
483 
485  statement new = copy_statement(s);
487  pips_assert("as many parameters as formal arguments\n",gen_length(call_arguments(ca)) == gen_length(fp));
488  for(list aiter = call_arguments(ca), piter=fp;
489  !ENDP(aiter);
490  POP(aiter),POP(piter)) {
491  expression arg = EXPRESSION(CAR(aiter));
492  entity fe = ENTITY(CAR(piter));
493  replace_entity_by_expression(new,fe,arg);// this perform the formal / effective parameter substitution
494  }
495  gen_free_list(fp);
496  return new;
497 }
498 
499 /* if some local variables are going to be accessed inter procedurally,
500  * promote them to global variables
501  */
502 static void promote_local_entities(statement s, entity caller, statement caller_statement) {
503  pips_assert("true", caller==caller && caller_statement==caller_statement);
505  list le = NIL;
506  SET_FOREACH(entity,e,re) {
508  !formal_parameter_p(e) ) {
509  le=CONS(ENTITY,e,le);
510  }
511  }
512  set_free(re);
513  gen_sort_list(le,(gen_cmp_func_t)compare_entities);//ensure determinism
514  FOREACH(ENTITY,e,le) {
515  entity new = entity_undefined;
516  if(entity_scalar_p(e)) {
518  entity_user_name(e),
521  );
522 
523  }
524  else {
525  pips_assert("not scalars -> array\n",entity_array_p(e));
527  entity_user_name(e),
531  );
532  }
539  }
540 }
541 
545  FOREACH(STATEMENT,s,c->stats) {
547  statement new = translate_arguments(ca,s);
548  /* there should be checks there ! */
549  insert_statement(parent,new,c->backward);
550  }
551  }
552 }
553 
554 
555 /* transform each caller into a load / call /store sequence */
557  FOREACH(STATEMENT,s,c->stats)
558  insert_statement(module_stat,s,c->backward);
559  gen_free_list(c->stats);c->stats=NIL;
560 }
563  if(ENDP(callers)) {
564  pips_user_warning("no caller for function `%s', falling back to intra-procedural delaying\n",get_current_module_name());
566  }
567  else {
568  list callers_statement = callers_to_statements(callers);
569 
570  for(list citer=callers,siter=callers_statement;!ENDP(citer);POP(citer),POP(siter)) {
571  c->caller=module_name_to_entity( STRING(CAR(citer)) );
572  c->caller_statement = STATEMENT(CAR(siter));
575  }
576 
577  for(list citer=callers,siter=callers_statement;!ENDP(citer);POP(citer),POP(siter)) {
578  string caller_name = STRING(CAR(citer));
579  statement caller_statement = STATEMENT(CAR(siter));
580  module_reorder(caller_statement);
581  DB_PUT_MEMORY_RESOURCE(DBR_CODE, caller_name,caller_statement);
582  DB_PUT_MEMORY_RESOURCE(DBR_CALLEES, caller_name,compute_callees(caller_statement));
583  }
584  }
585 }
586 
587 
595 }
601 
602 }
603 
604 /* This phase looks for load or save statements that can be
605  * put out of the loop body and move these statements, if possible.
606  */
608 {
609  /* Get the code of the module. */
611  statement module_stat = (statement)db_get_memory_resource(DBR_CODE, module_name, true);
612  set_ordering_to_statement(module_stat);
614  set_current_module_statement( module_stat);
616  (statement_effects)db_get_memory_resource(DBR_PROPER_EFFECTS, module_name, true)
617  );
620  (statement_effects)db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true)
621  );
622 
623 
624  debug_on("DELAY_COMMUNICATIONS_DEBUG_LEVEL");
627 
628  /* Go through all the statements */
629  context c = { true, NIL, true, false , NULL, NULL };
630 
631  /* then a backward translation */
632  delay_communications_statement(module_stat,&c,NULL);
633 
634  /* propagate inter procedurally , except if we have no caller*/
637  else
639 
640  if(c.need_flatten)
642 
643  /* clean badly generated sequences */
644  clean_up_sequences(module_stat);
645 
647 
648 
649  pips_assert("Statement is consistent\n" , statement_consistent_p(module_stat));
650 
651  module_reorder(module_stat);
652  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module_name, module_stat);
653  DB_PUT_MEMORY_RESOURCE(DBR_CALLEES, module_name, compute_callees(module_stat));
654 
655  debug_off();
656 
662 
663  return c.result;
664 }
668 }
672 }
673 
675 {
676  /* Get the code of the module. */
678  statement module_stat = (statement)db_get_memory_resource(DBR_CODE, module_name, true);
679  set_ordering_to_statement(module_stat);
681  set_current_module_statement( module_stat);
683  (statement_effects)db_get_memory_resource(DBR_PROPER_EFFECTS, module_name, true)
684  );
687  (statement_effects)db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true)
688  );
690 
692 
693  debug_on("DELAY_COMMUNICATIONS_DEBUG_LEVEL");
694 
695 
696 
697  /* Go through all the statements */
698  context c = { true, NIL, false, false, NULL, NULL };
699 
700  /* a first forward translation */
701  delay_communications_statement(module_stat,&c,NULL);
702 
703  /* propagate inter procedurally , except if we have no caller*/
706  else
708 
709  if(c.need_flatten)
711 
712  /* clean badly generated sequences */
713  clean_up_sequences(module_stat);
714 
716 
717  pips_assert("Statement is consistent\n" , statement_consistent_p(module_stat));
718 
719  module_reorder(module_stat);
720  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module_name, module_stat);
721  DB_PUT_MEMORY_RESOURCE(DBR_CALLEES, module_name, compute_callees(module_stat));
722 
723  debug_off();
724 
730 
731  return c.result;
732 }
736 }
740 }
741 
743  pips_assert("called on dmas",simd_dma_stat_p(s0) && simd_dma_stat_p(s1));
746  list pr=NIL,pw=NIL,sr=NIL,sw=NIL;
747  FOREACH(REGION,r,p_reg) {
749  if(region_write_p(r)) {
750  pw=CONS(REGION,r,pw);
751  }
752  else {
753  pr=CONS(REGION,r,pr);
754  }
755  }
756  }
757  FOREACH(REGION,r,s_reg) {
759  if(region_write_p(r)) {
760  sw=CONS(REGION,r,sw);
761  }
762  else {
763  sr=CONS(REGION,r,sr);
764  }
765  }
766  }
767  /* this occurs when structures are involved */
768  if( ENDP(sw) ||
769  ENDP(sr) ||
770  ENDP(pw) ||
771  ENDP(pr)) {
772  pips_user_warning("regions for dma not properly computed\n");
773  return false;
774  }
775  else {
776  /* dma annihilates */
777  bool annihilate = gen_length(pw) == gen_length(sr) &&
778  gen_length(pr) == gen_length(sw) ;
779  if( annihilate) {
780  for(list i=pw,j=sr;!ENDP(i)&&!ENDP(j);POP(i),POP(j)) {
781  region ri = REGION(CAR(i)),
782  rj = REGION(CAR(j));
783  if(!( annihilate = (reference_equal_p(region_any_reference(ri),region_any_reference(rj)) &&
785  ) ) break;
786 
787  }
788  if(annihilate) {
789  for(list i=sw,j=pr;!ENDP(i)&&!ENDP(j);POP(i),POP(j)) {
790  region ri = REGION(CAR(i)),
791  rj = REGION(CAR(j));
792  if(!( annihilate = (reference_equal_p(region_any_reference(ri),region_any_reference(rj)) &&
794  ) ) break;
795 
796  }
797  }
798  }
799  return annihilate;
800  }
801 }
802 
803 static void do_remove_redundant_communications_in_sequence(sequence s, bool *need_flatten){
804  pips_assert("true",need_flatten==need_flatten );
807  FOREACH(STATEMENT,st,ts) {
808  if(simd_dma_stat_p(st)) {
809  if(!statement_undefined_p(prev)) { // do they annihilate each other ?
810  if(dmas_invert_p(st,prev)) {
811  /* remove the second statements from the original sequence
812  * if we have load ; store , the store is useless
813  * and the load will be removed by a used_def_elim phase
814  * if we have store ; load, it 's the same
815  */
816  // gen_remove_once(&sequence_statements(s),prev);
818  }
819  else
820  prev=st;
821  prev=statement_undefined;
822  }
823  else
824  prev=st;
825  }
826  else
827  prev=statement_undefined;
828  }
829  gen_free_list(ts);
830 }
831 
832 static void select_independent_dmas(list * stats, statement parent) {
833  list rtmp = NIL;
834  FOREACH(STATEMENT,st,*stats)
835  if(simd_dma_stat_p(st)) {
836  bool conflict = false;
837  FOREACH(STATEMENT,st2,rtmp) {
838  if((conflict=statements_conflict_p(st,st2)))
839  break;
840  }
841  conflict|=statements_conflict_p(st,parent);
842  if(conflict) break;
843  rtmp=CONS(STATEMENT,st,rtmp);
844  }
845  else
846  break;
847  gen_free_list(*stats);
848  *stats=rtmp;
849 }
850 
852  bool need_flatten=false;
853  if(statement_block_p(body)) {
854  list b = statement_block(body);
855  list iordered=b;
856  /* skip declarations */
857  while(!ENDP(iordered) &&
858  declaration_statement_p(STATEMENT(CAR(iordered))) ) POP(iordered);
859  bool skipped_declarations= (iordered != b);
860  list reversed = gen_nreverse(gen_copy_seq(iordered));
861  /* look for heading dma statements */
862  iordered=gen_copy_seq(iordered); // to be consistent with `reversed' allocation
863  select_independent_dmas(&iordered, parent);
864  /* look for trailing dma statements */
865  select_independent_dmas(&reversed, parent);
866 
867  bool did_something=false;
868  for(list oter=iordered;!ENDP(oter);POP(oter)) {
869  statement os = STATEMENT(CAR(oter));
870  FOREACH(STATEMENT,rs,reversed) {
871  if(simd_dma_stat_p(os) &&
872  simd_dma_stat_p(rs) &&
873  dmas_invert_p(os,rs)) {
874  gen_remove_once(&b,rs);
875  gen_remove_once(&b,os);
876  /* insert them around the loop */
877  insert_statement(parent,os,true);
878  insert_statement(parent,rs,false);
879  /* flatten_code if needed */
880  set re = get_referenced_entities(os);
881  set de = set_make(set_pointer);
883  if(set_intersection_p(de,re)) need_flatten = true;
884  set_free(de);set_free(re);
885  /* and remove them from the alternate list */
886  gen_remove_once(&b,rs);
887  gen_remove_once(&reversed,os);
888  did_something=true;
889  break;
890  }
891  }
892  }
893  gen_free_list(iordered);
894  gen_free_list(reversed);
895  if(did_something && skipped_declarations)
896  need_flatten=true;
898  }
899  return need_flatten;
900 }
901 
902 static void do_remove_redundant_communications_in_loop( loop l, bool *need_flatten) {
904 }
905 
906 static void do_remove_redundant_communications_in_whileloop( whileloop l, bool *need_flatten) {
908 }
909 
910 static void do_remove_redundant_communications_in_forloop( forloop l, bool *need_flatten) {
912 }
913 
915  bool need_flatten=false;
916  gen_context_multi_recurse(s,&need_flatten,
921  NULL);
922  return need_flatten;
923 }
924 static bool delay_communications(const char * module_name)
925 {
926  /* Get the code of the module. */
928  statement module_stat = (statement)db_get_memory_resource(DBR_CODE, module_name, true);
930  set_current_module_statement( module_stat);
931  set_ordering_to_statement(module_stat);
932 
934  (statement_effects)db_get_memory_resource(DBR_PROPER_EFFECTS, module_name, true)
935  );
939  );
941 
942  debug_on("DELAY_COMMUNICATIONS_DEBUG_LEVEL");
943  bool need_flatten=
944  remove_redundant_communications(module_stat);
945 
946  /* clean badly generated sequences */
947  clean_up_sequences(module_stat);
948 
949  if(need_flatten)
951 
952 
953  pips_assert("Statement is consistent\n" , statement_consistent_p(module_stat));
954 
955  module_reorder(module_stat);
956  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module_name, module_stat);
957  DB_PUT_MEMORY_RESOURCE(DBR_CALLEES, module_name, compute_callees(module_stat));
958 
959  debug_off();
961 
967 
968  return true;
969 }
973 }
977 }
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
void free_preference(preference p)
Definition: ri.c:1829
statement copy_statement(statement p)
STATEMENT.
Definition: ri.c:2186
bool statement_consistent_p(statement p)
Definition: ri.c:2195
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
bool delay_communications_intra(const char *module_name)
Definition: delay.c:974
bool simd_load_stat_p(statement stat)
Definition: delay.c:111
bool simd_stat_p(statement stat)
This function returns true if the statement is a simd statement.
Definition: delay.c:135
bool delay_communications_inter(const char *module_name)
Definition: delay.c:970
bool delay_store_communications_intra(char *module_name)
Definition: delay.c:737
static void do_remove_redundant_communications_in_whileloop(whileloop l, bool *need_flatten)
Definition: delay.c:906
static bool delay_communications(const char *module_name)
Definition: delay.c:924
static void delay_communications_intraprocedurally(statement module_stat, context *c)
transform each caller into a load / call /store sequence
Definition: delay.c:556
static void delay_communications_reset()
Definition: delay.c:596
static void create_block_if_needed(statement *s, list **block)
Definition: delay.c:279
static void delay_communications_statement(statement, context *, list *block)
Definition: delay.c:455
static void manage_conflicts(statement s, context *c, bool before, list *block)
Definition: delay.c:304
static void do_remove_redundant_communications_in_loop(loop l, bool *need_flatten)
Definition: delay.c:902
bool simd_store_stat_p(statement stat)
Definition: delay.c:119
static bool simd_work_call_p(call c)
Definition: delay.c:100
bool simd_dma_stat_p(statement stat)
This function returns true if the statement is a simd loadsave statement.
Definition: delay.c:127
bool delay_load_communications_intra(char *module_name)
Definition: delay.c:669
static void delay_communications_test(statement s, context *c, list *block)
Definition: delay.c:332
static bool remove_redundant_communications(statement s)
Definition: delay.c:914
static void delay_communications_interprocedurally(context *c)
Definition: delay.c:561
dg_vertex_label vertex_label
Definition: delay.c:64
static void do_delay_communications_interprocedurally(call ca, context *c)
Definition: delay.c:542
static bool statements_conflict_relaxed_p(statement s0, statement s1, bool load_p)
same as statements_conflict_p but W-* conflicts are ignored if load_p, R-* conflicts are ignored if n...
Definition: delay.c:192
static bool dmas_invert_p(statement s0, statement s1)
Definition: delay.c:742
bool delay_store_communications(char *module_name)
Definition: delay.c:674
static bool statements_conflict_p(statement s0, statement s1)
checks if there exist a conflict between s0 and s1 according to the dependency graph
Definition: delay.c:161
static void delay_communications_call(statement s, context *c, list *block)
Definition: delay.c:316
bool simd_work_stat_p(statement stat)
Definition: delay.c:115
static void select_independent_dmas(list *stats, statement parent)
Definition: delay.c:832
static bool dma_conflict_p(conflict c)
Definition: delay.c:142
bool delay_store_communications_inter(char *module_name)
Definition: delay.c:733
static bool recurse_statements_conflict_p(statement s, statement in)
checks if there is a conflict between s and any statement in in
Definition: delay.c:247
dg_arc_label arc_label
Definition: delay.c:63
static void do_recurse_statements_conflict_p(statement s, conflict_t *c)
helper for recurse_statements_conflict_p
Definition: delay.c:239
static bool do_remove_redundant_communications_in_anyloop(statement parent, statement body)
Definition: delay.c:851
static bool simd_store_call_p(call c)
Definition: delay.c:105
static void promote_local_entities(statement s, entity caller, statement caller_statement)
if some local variables are going to be accessed inter procedurally, promote them to global variables
Definition: delay.c:502
static context context_dup(context *c)
Definition: delay.c:262
static bool simd_load_call_p(call c)
Definition: delay.c:95
static void delay_communications_init()
Definition: delay.c:589
static graph dependence_graph
Definition: delay.c:93
bool delay_load_communications_inter(char *module_name)
Definition: delay.c:665
static statement translate_arguments(call ca, statement s)
Definition: delay.c:484
bool delay_load_communications(char *module_name)
This phase looks for load or save statements that can be put out of the loop body and move these stat...
Definition: delay.c:607
void remove_preferences(void *obj)
entry point to transform preferences in references
Definition: delay.c:89
static void insert_statement_in_block(statement s, statement inserted, bool before, list *block)
Definition: delay.c:292
static void do_remove_redundant_communications_in_forloop(forloop l, bool *need_flatten)
Definition: delay.c:910
static void do_remove_redundant_communications_in_sequence(sequence s, bool *need_flatten)
Definition: delay.c:803
static bool __delay_communications_patch_properties
Definition: delay.c:588
static void delay_communications_sequence(sequence s, context *c, list *block)
Definition: delay.c:270
static void delay_communications_anyloop(statement s, context *c, list *block)
Definition: delay.c:407
static bool delay_communications_interprocedurally_p
Definition: delay.c:73
static bool dma_statements_conflict_p(statement s0, statement s1)
Definition: delay.c:216
static bool do_remove_preference(cell c)
helper to transform preferences in references
Definition: delay.c:76
static const char * caller_name
Definition: alias_check.c:122
list callers_to_statements(list callers)
given a list callers of module name calling module called module return a list of their body
Definition: callgraph.c:163
callees compute_callees(const statement stat)
Recompute the callees of a module statement.
Definition: callgraph.c:355
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
#define conflict_sink(x)
Definition: dg.h:167
#define CONFLICT(x)
CONFLICT.
Definition: dg.h:134
#define dg_arc_label_conflicts(x)
Definition: dg.h:201
struct _newgen_struct_conflict_ * conflict
Definition: dg.h:52
#define conflict_source(x)
Definition: dg.h:165
#define region_any_reference(reg)
To be avoided.
#define region_write_p(reg)
#define region_system(reg)
#define REGION
#define region
simulation of the type region
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
void set_cumulated_rw_effects(statement_effects)
list load_cumulated_rw_effects_list(statement)
void reset_cumulated_rw_effects(void)
statement_effects get_proper_rw_effects(void)
#define effect_write_p(eff)
#define effect_read_p(eff)
#define effect_scalar_p(eff) entity_scalar_p(effect_entity(eff))
#define cell_reference(x)
Definition: effects.h:469
#define cell_preference(x)
Definition: effects.h:472
#define cell_domain
newgen_cell_interpretation_domain_defined
Definition: effects.h:85
@ is_cell_reference
Definition: effects.h:445
#define cell_tag(x)
Definition: effects.h:466
#define descriptor_convex_p(x)
Definition: effects.h:599
#define effect_descriptor(x)
Definition: effects.h:646
#define descriptor_convex(x)
Definition: effects.h:601
#define cell_preference_p(x)
Definition: effects.h:470
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
char * get_string_property(const char *)
void statement_split_initializations(statement s)
Recurse through the statements of s and split local declarations.
Definition: flatten_code.c:733
bool statement_flatten_declarations(entity module, statement s)
flatten_code.c
Definition: flatten_code.c:509
#define gen_chunk_undefined_p(c)
Definition: genC.h:75
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define STRING(x)
Definition: genC.h:87
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void free(void *)
#define successor_vertex(x)
Definition: graph.h:118
#define successor_arc_label(x)
Definition: graph.h:116
struct _newgen_struct_graph_ * graph
Definition: graph.h:31
#define vertex_successors(x)
Definition: graph.h:154
#define graph_undefined_p(x)
Definition: graph.h:61
#define SUCCESSOR(x)
SUCCESSOR.
Definition: graph.h:86
#define graph_vertices(x)
Definition: graph.h:82
#define graph_undefined
Definition: graph.h:60
#define VERTEX(x)
VERTEX.
Definition: graph.h:122
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
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
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void replace_entity(void *s, entity old, entity new)
per variable version of replace_entities.
Definition: replace.c:113
void replace_entity_by_expression(void *s, entity ent, expression exp)
replace all reference to entity ent by expression exp in s.
Definition: replace.c:220
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_ancestor(int, const void *)
return the first ancestor object found of the given type.
Definition: genClib.c:3560
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
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
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#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
void * gen_find_eq(const void *item, const list seq)
Definition: list.c:422
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
void gen_sort_list(list l, gen_cmp_func_t compare)
Sorts a list of gen_chunks in place, to avoid allocations...
Definition: list.c:796
void gen_insert_after(const void *no, const void *o, list l)
Definition: list.c:223
list gen_insert_before(const void *no, const void *o, list l)
Definition: list.c:238
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
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
list statement_block(statement)
Get the list of block statements of a statement sequence.
Definition: statement.c:1338
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
test statement_test(statement)
Get the test of a statement.
Definition: statement.c:1348
call statement_call(statement)
Get the call of a statement.
Definition: statement.c:1406
whileloop statement_whileloop(statement)
Get the whileloop of a statement.
Definition: statement.c:1383
forloop statement_forloop(statement)
Get the forloop of a statement.
Definition: statement.c:1426
bool statement_whileloop_p(statement)
Definition: statement.c:354
bool statement_call_p(statement)
Definition: statement.c:364
bool statement_forloop_p(statement)
Definition: statement.c:374
bool statement_loop_p(statement)
Definition: statement.c:349
statement update_statement_instruction(statement, instruction)
Replace the instruction in statement s by instruction i.
Definition: statement.c:3039
bool return_statement_p(statement)
Test if a statement is a C or Fortran "return".
Definition: statement.c:172
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
bool empty_comments_p(const char *)
Definition: statement.c:107
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
statement vertex_to_statement(vertex v)
Vertex_to_statement looks for the statement that is pointed to by vertex v.
Definition: util.c:45
#define debug_on(env)
Definition: misc-local.h:157
#define pips_user_warning
Definition: misc-local.h:146
#define same_stringn_p(a, b, c)
Definition: misc-local.h:199
#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
set set_assign_list(set, const list)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474
bool set_intersection_p(const set, const set)
returns whether s1 n s2 <> 0 complexity of the intersection
Definition: set.c:288
#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
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ 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 false
Definition: newgen_types.h:80
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
hash_table set_ordering_to_statement(statement s)
To be used instead of initialize_ordering_to_statement() to make sure that the hash table ots is in s...
Definition: ordering.c:172
void reset_ordering_to_statement(void)
Reset the mapping from ordering to statement.
Definition: ordering.c:185
static char * module
Definition: pips.c:74
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define statement_block_p(stat)
#define empty_comments
Empty comments (i.e.
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
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
int compare_entities(const entity *pe1, const entity *pe2)
Comparison function for qsort.
Definition: entity.c:1328
bool entity_array_p(entity e)
Is e a variable with an array type?
Definition: entity.c:754
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
bool local_entity_of_module_p(entity e, entity module)
This test shows that "e" has been declared in "module".
Definition: entity.c:1069
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
basic entity_basic(entity e)
return the basic associated to entity e if it's a function/variable/constant basic_undefined otherwis...
Definition: entity.c:1380
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
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
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
bool array_reference_p(reference r)
predicates on references
Definition: expression.c:1861
list module_formal_parameters(entity func)
list module_formal_parameters(entity func) input : an entity representing a function.
Definition: module.c:327
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
entity make_new_array_variable_with_prefix(const char *, entity, basic, list)
J'ai ameliore la fonction make_new_scalar_variable_with_prefix
Definition: variable.c:785
void RemoveLocalEntityFromDeclarations(entity, entity, statement)
Definition: variable.c:120
bool formal_parameter_p(entity)
Definition: variable.c:1489
entity make_new_scalar_variable_with_prefix(const char *, entity, basic)
Create a new scalar variable of type b in the given module.
Definition: variable.c:592
#define forloop_domain
newgen_extensions_domain_defined
Definition: ri.h:178
#define loop_body(x)
Definition: ri.h:1644
#define call_function(x)
Definition: ri.h:709
#define callees_callees(x)
Definition: ri.h:675
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define statement_ordering(x)
Definition: ri.h:2454
#define value_unknown_p(x)
Definition: ri.h:3077
#define test_false(x)
Definition: ri.h:2837
#define type_variable(x)
Definition: ri.h:2949
#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 instruction_undefined
Definition: ri.h:1454
#define entity_undefined
Definition: ri.h:2761
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_expression
Definition: ri.h:1478
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define instruction_sequence(x)
Definition: ri.h:1514
#define preference_reference(x)
Definition: ri.h:2102
#define variable_dimensions(x)
Definition: ri.h:3122
#define whileloop_body(x)
Definition: ri.h:3162
#define whileloop_domain
newgen_variable_domain_defined
Definition: ri.h:466
#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 call_arguments(x)
Definition: ri.h:711
#define statement_undefined_p(x)
Definition: ri.h:2420
#define entity_type(x)
Definition: ri.h:2792
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
#define forloop_body(x)
Definition: ri.h:1372
#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
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87
s1
Definition: set.c:247
#define intptr_t
Definition: stdint.in.h:294
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
helper for do_recurse_statements_conflict_p
Definition: delay.c:233
statement s
Definition: delay.c:234
bool conflict
Definition: delay.c:235
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: delay.c:253
entity caller
Definition: delay.c:258
bool need_flatten
Definition: delay.c:257
list stats
Definition: delay.c:255
statement caller_statement
Definition: delay.c:259
bool result
Definition: delay.c:254
bool backward
Definition: delay.c:256
#define sc_inclusion_p(ps1, ps2)
Definition: union-local.h:80
#define sc_equal_p(ps1, ps2)
Definition: union-local.h:83
void AddEntityToModuleCompilationUnit(entity e, entity module)
Definition: module.c:301
entity module_entity_to_compilation_unit_entity(entity m)
Retrieve the compilation unit containing a module definition.
Definition: module.c:116