PIPS
comEngine_generate_code.c
Go to the documentation of this file.
1 /*
2 
3  $Id: comEngine_generate_code.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /*
28 This file contains functions used to generate the MMCDs generation code and
29 The HRE code if we want to have only one process on the HRE
30  */
31 
32 #include <stdio.h>
33 #include <ctype.h>
34 
35 #include "genC.h"
36 #include "linear.h"
37 #include "ri.h"
38 #include "effects.h"
39 
40 #include "resources.h"
41 
42 #include "misc.h"
43 #include "ri-util.h"
44 #include "prettyprint.h"
45 #include "effects-util.h"
46 
47 #include "text-util.h"
48 #include "properties.h"
49 
50 
51 #include "ray_dte.h"
52 #include "sommet.h"
53 #include "sg.h"
54 #include "polyedre.h"
55 
56 #include "phrase_tools.h"
57 
58 #include "effects-generic.h"
59 #include "effects-simple.h"
60 #include "effects-convex.h"
61 
62 #include "phrase_distribution.h"
63 #include "comEngine.h"
64 #include "phrase.h"
65 
67 
68 // These variable is used to know if we are generating the MMCD code
69 // or the HRE code
70 bool gGenHRE = false;
71 
72 static bool COM_OPT;
73 
74 // This variable if the execution MMCD have been put for the current
75 // computation kernel
76 static bool gExecPut;
77 
78 static list glCurRep = NIL;
80 static list glCurLoop = NIL;
81 
82 // This is used to make sure that the loop indices out effects are correct
84 
85 // This stores the initialization for the toggle variables. These variables
86 // perform a switch mechanism to make sure that, because of the
87 // pipeline, one fifo will not be used to load data, compute data and store
88 // data at the same step.
90 
91 /*
92 This function create a new scalar variable
93  */
95  basic bas)
96 {
97  entity retEnt = entity_undefined;
100  bas);
101  AddEntityToCurrentModule(retEnt);
102 
103  return retEnt;
104 }
105 
106 /*
107 This function is called to prevent the optimization phase if a loop contains
108 some data dependence
109  */
110 static void fill_gLoopToOpt(list lRef)
111 {
112  if(lRef != NIL)
113  {
114  MAP(STATEMENT, loopStat,
115  {
116  hash_put(gLoopToOpt, loopStat, (void *)false);
117  }, glCurLoop);
118  }
119 }
120 
121 /*
122 This function associate a toggle entities list to a loop statement
123 from the list of reference lRef.
124  */
125 static void fill_gLoopToToggleEnt(statement stat, list lRef)
126 {
127  list lDone = NIL;
128 
129  // Go through the reference list attached to this loop
130  FOREACH(REFERENCE, curRef, lRef)
131  {
132  // Get the fifo number for the current reference
133  intptr_t fifoNum = (intptr_t)hash_get(gRefToFifo, curRef);
134 
135  pips_assert("fifoNum != HASH_UNDEFINED_VALUE",
136  fifoNum != (intptr_t)HASH_UNDEFINED_VALUE);
137 
138  // Get the fifo offset for the cureent reference
139  intptr_t inc = (intptr_t)hash_get(gRefToFifoOff, (void *)fifoNum);
140 
141  pips_assert("inc != HASH_UNDEFINED_VALUE",
143 
144  bool bDone = false;
145 
146  // If a toggle variable has already been created for this loop,
147  // then continue
148  MAP(INT, incDone,
149  {
150  if(inc == incDone)
151  {
152  bDone = true;
153  break;
154  }
155  }, lDone);
156 
157  if(bDone)
158  continue;
159 
160  lDone = CONS(INT, inc, lDone);
161 
162  // Create a new toggle variable
163  entity toggleEnt =
165  make_basic(is_basic_int, (void *)4));
166 
167  list lToggleEnt = hash_get(gLoopToToggleEnt, stat);
168 
169  if(lToggleEnt == HASH_UNDEFINED_VALUE)
170  {
171  lToggleEnt = NIL;
172  }
173 
174  // Store the new variable in the list of toggle variables
175  lToggleEnt = CONS(ENTITY, toggleEnt, lToggleEnt);
176 
177  hash_put(gLoopToToggleEnt, stat, lToggleEnt);
178 
179  // Associate the value corresponding to the fifo offset to the toggle
180  // variable
181  hash_put(gToggleToInc, toggleEnt, (void *)inc);
182 
183  }
184 }
185 
186 /*
187 This function makes a statement to initialize a toggle variable
188  */
190 {
192  int_to_expression(0));
193 }
194 
195 /*
196 This function updates the toggle variables initialization statements list.
197  */
199 {
200  list lToggleEnt = hash_get(gLoopToToggleEnt, stat);
201 
202  pips_assert("lToggleEnt != HASH_UNDEFINED_VALUE",
203  lToggleEnt != HASH_UNDEFINED_VALUE);
204 
205  list lStats = NIL;
206 
207  MAP(ENTITY, toggleEnt,
208  {
209  // Create an initialization statement for the curren toggle variable
210  statement toggleStat = make_toggle_init_statement(toggleEnt);
211 
212  lStats = gen_nconc(lStats, CONS(STATEMENT, toggleStat, NIL));
213  }, lToggleEnt);
214 
216 }
217 
218 /*
219 This function makes a statement to increment the value of the toggle
220 variable toggleEnt.
221  */
223 {
225  entity_to_expression(toggleEnt),
226  int_to_expression(val),
227  NULL);
228 
229  expression modExp =
231  modArg));
232 
234  modExp);
235 }
236 
237 /*
238 This function makes statements to increment the value of the toggle
239 variables associated to the loop
240  */
241 static void add_toggle_inc_statements(statement stat, list lInStats)
242 {
243  list lToggleEnt = hash_get(gLoopToToggleEnt, stat);
244 
245  pips_assert("lToggleEnt != HASH_UNDEFINED_VALUE",
246  lToggleEnt!= HASH_UNDEFINED_VALUE);
247 
248  // The loop we consider is the first statement of the list lInStats
249  statement newLoopStat = STATEMENT(CAR(lInStats));
250 
251  pips_assert("newLoopStat is a loop statement",
252  statement_loop_p(newLoopStat));
253 
254  statement body = loop_body(statement_loop(newLoopStat));
255 
256  list lStats = CONS(STATEMENT, body, NIL);
257 
258  MAP(STATEMENT, loopStat,
259  {
260  if(loopStat == STATEMENT(CAR(glCurLoop)))
261  {
262  continue;
263  }
264 
265  entity inInd = hash_get(gHtCurNewInd, loopStat);
266 
267  statement indStat = make_init_newInd_stat(loopStat, inInd);
268 
269  if(indStat != statement_undefined)
270  {
271  lStats = gen_nconc(CONS(STATEMENT, indStat, NIL), lStats);
272  }
273  }, glCurLoop);
274 
275  // For each toggle variable, create a statement to increment it
276  MAP(ENTITY, toggleEnt,
277  {
278  statement mmcdStat = make_toggle_mmcd(toggleEnt);
279 
280  lStats = gen_nconc(CONS(STATEMENT, mmcdStat, NIL), lStats);
281 
282  intptr_t inc = (intptr_t)hash_get(gToggleToInc, toggleEnt);
283 
284  statement toggleStat =
285  make_toggle_inc_statement(toggleEnt, inc);
286 
287  lStats = gen_nconc(lStats, CONS(STATEMENT, toggleStat, NIL));
288  }, lToggleEnt);
289 
290  loop_body(statement_loop(newLoopStat)) = make_block_statement(lStats);
291 }
292 
293 /*
294 This function performs some transformation on the inner loop of the
295 loop tiling operation
296  */
297 static statement make_loopStat1(statement stat, entity transferSize,
298  statement innerStat, entity newOuterInd,
299  list lSupportedRef, hash_table htOffset,
300  expression bufferSizeExp, entity newInnerInd)
301 {
302  loop curLoop = statement_loop(stat);
303 
304  if(innerStat != statement_undefined)
305  {
306  expression indExp = entity_to_expression(newInnerInd);
307 
308  // If we are generating the HRE code, then replace the references by
309  // the private HRE references
310  if(gGenHRE)
311  {
312  if(!COM_OPT)
313  {
314  process_replacement_HRE(lSupportedRef, indExp, &loop_body(statement_loop(innerStat)));
315  }
316  }
317 
318  free_expression(indExp);
319  }
320 
321  // Add some statements to the innerStat
322  list lStats = NIL;
323  if(gGenHRE)
324  {
325  lStats = make_loop_lStats_HRE(stat, transferSize,
326  innerStat, newOuterInd,
327  lSupportedRef, htOffset,
328  bufferSizeExp);
329  }
330  else
331  {
332  lStats = make_loop_lStats_proc(stat, transferSize,
333  innerStat, newOuterInd,
334  lSupportedRef, htOffset,
335  bufferSizeExp);
336  }
337 
338  innerStat = make_block_statement(lStats);
339 
340  // The following lines create the outer loop of the loop tiling
341  // operation
342  range outerRange1 = make_range(copy_expression(range_lower(loop_range(curLoop))),
344  copy_expression(bufferSizeExp));
345 
346  loop outerLoop1 = make_loop(newOuterInd,
347  outerRange1,
348  innerStat,
349  loop_label(curLoop),
351  NIL);
352 
357  make_instruction_loop(outerLoop1),NIL,NULL,
359 }
360 
361 #if 0
362 static statement make_init_prev_ind(statement oldBody)
363 {
364  list lStats = NIL;
365 
366  MAP(STATEMENT, loopStat,
367  {
368  if(loopStat == STATEMENT(CAR(glCurLoop)))
369  {
370  continue;
371  }
372 
373  entity inInd = hash_get(gHtCurNewInd, loopStat);
374 
375  statement indStat = make_init_newInd_stat(loopStat, inInd);
376 
377  if(indStat != statement_undefined)
378  {
379  lStats = gen_nconc(CONS(STATEMENT, indStat, NIL), lStats);
380  }
381  }, glCurLoop);
382 
383  lStats = gen_nconc(lStats, CONS(STATEMENT, oldBody, NIL));
384 
385  return make_block_statement(lStats);
386 }
387 #endif
388 
389 /*
390 This function performs a loop tiling operation from the loop statement
391 stat.
392  */
394  list lSupportedRef, list lUnSupportedRef,
395  hash_table htOffset, expression bufferSizeExp,
396  entity newOuterInd, entity newInnerInd)
397 {
398  loop curLoop = statement_loop(stat);
399 
400  statement innerStat1 = statement_undefined;
401 
402  statement loopStat1 = statement_undefined;
403 
404  entity transferSize =
406  make_basic(is_basic_int, (void*)4));
407 
408  // If the new body is not undefined, then create the inner loop.
409  if((newBody != statement_undefined) ||
410  (lUnSupportedRef != NIL))
411  {
412  // If there are some unsupported references, then let us add some
413  // statements to the code to support them
414  if(lUnSupportedRef != NIL)
415  {
416  // Let us do what needs to be done to handle the references list
417  if(gGenHRE)
418  {
419  if(!COM_OPT)
420  {
421  process_replacement_HRE(lUnSupportedRef, expression_undefined, &newBody);
422  }
423 
424  newBody = generate_stat_from_ref_list_HRE(lUnSupportedRef, newBody);
425  }
426  else
427  {
428  list lToggleEnt = hash_get(gLoopToToggleEnt,
429  loop_body(statement_loop(stat)));
430 
431  if(lToggleEnt == HASH_UNDEFINED_VALUE)
432  {
433  lToggleEnt = NIL;
434  }
435 
436  newBody = generate_stat_from_ref_list_proc(lUnSupportedRef,
437  lToggleEnt,
438  newBody);
439 
440  fill_gLoopToOpt(lUnSupportedRef);
441  }
442  }
443  else if(newBody == statement_undefined)
444  {
445  newBody = make_block_statement(NIL);
446  }
447 
448  //newBody = make_init_prev_ind(newBody);
449 
450  // The following lines create the inner loop of the loop tiling
451  // operation
452  range innerRange = make_range(int_to_expression(0),
453  entity_to_expression(transferSize),
454  int_to_expression(1));
455 
456  loop innerLoop = make_loop(newInnerInd,
457  innerRange,
458  newBody,
459  loop_label(curLoop),
461  NIL);
462 
463  innerStat1 = make_statement(entity_empty_label(),
467  make_instruction_loop(innerLoop),NIL,NULL,
469 
470  if(!gGenHRE)
471  {
472  process_innerStat1_proc(innerStat1, loop_index(curLoop),
473  newOuterInd, newInnerInd);
474  }
475 
476  //printf("innerStat1\n");
477  //print_statement(innerStat1);
478 
479  // Let us try and see if we can optimize the transfers
480  if(COM_OPT)
481  {
482  innerStat1 = comEngine_opt_loop_interchange(stat, innerStat1,
483  newOuterInd);
484  }
485 
486  }
487 
488  // This function finishes the loop tiling operation
489  loopStat1 = make_loopStat1(stat, transferSize,
490  innerStat1, newOuterInd,
491  lSupportedRef, htOffset,
492  bufferSizeExp, newInnerInd);
493 
494  return loopStat1;
495 }
496 
497 /*
498 This function generates the MMCD code or the HRE code from a loop
499 statement.
500  */
502 {
503  printf("generate_code_loop\n");
504  print_statement(stat);
505 
506  statement newBody = statement_undefined;
507 
508  list lStats = NIL;
509 
510  hash_table htOffset = hash_get(gStatToHtOffset, stat);
511 
512  if(!gGenHRE)
513  {
514  pips_assert("htOffset != HASH_UNDEFINED_VALUE",
515  htOffset != HASH_UNDEFINED_VALUE);
516  }
517 
518  loop curLoop = statement_loop(stat);
519 
520  list lRef = hash_get(gLoopToRef, stat);
521 
522  if(lRef == HASH_UNDEFINED_VALUE)
523  {
524  lRef = NIL;
525  }
526 
527  list lSupportedRef = NIL;
528  list lUnSupportedRef = NIL;
529 
530  // Store the list of supported and unsupported references for loop
531  // statement stat.
533  &lSupportedRef, &lUnSupportedRef);
534 
535  // Create a new index
536  entity newOuterInd =
538  copy_basic(entity_basic(loop_index(curLoop))));
539 
540  // Memorize the index created in the hash_table gLoopToOuterInd
541  hash_put(gLoopToOuterInd, stat, newOuterInd);
542 
543  // Create a new index
544  entity newInnerInd =
546  copy_basic(entity_basic(loop_index(curLoop))));
547 
548  // If we are generating the MMCD code, then create the fifos for the
549  // supported and unsupported references
550  if(!gGenHRE)
551  {
552  create_realFifo_proc(stat, lSupportedRef);
553  create_realFifo_proc(stat, lUnSupportedRef);
554  }
555 
556  // Create the toggle references and store them in gLoopToToggleEnt
557  fill_gLoopToToggleEnt(stat, lSupportedRef);
558  fill_gLoopToToggleEnt(loop_body(statement_loop(stat)), lUnSupportedRef);
559 
560  // Add the loop to the current loops list
561  glCurLoop = CONS(STATEMENT, stat, glCurLoop);
562 
563  // Memorize the current newInnerInd in gHtCurNewInd
564  hash_put(gHtCurNewInd, stat, newInnerInd);
565 
566  hash_put(gLoopToOpt, stat, (void *)true);
567 
568  gExecPut = false;
569 
570  // Get the new statements for the loop body
571  newBody = generate_code_function(loop_body(curLoop), false);
572 
573  gExecPut = false;
574 
575  printf("newBody real\n");
576  if(newBody == statement_undefined)
577  {
578  printf("undefined\n");
579  }
580  else
581  {
582  print_statement(newBody);
583  }
584 
585  // If there are some supported references, the let us perform a loop
586  // tiling operation
587  if(lSupportedRef != NIL)
588  {
589  expression bufferSizeExp = expression_undefined;
590 
591  bufferSizeExp = copy_expression(gBufferSizeEnt);
592 
593  statement newStat = usual_loop_tiling(stat, newBody,
594  lSupportedRef, lUnSupportedRef,
595  htOffset, bufferSizeExp,
596  newOuterInd, newInnerInd);
597 
598  list lToggleEnt = hash_get(gLoopToToggleEnt, stat);
599 
600  if(lToggleEnt != HASH_UNDEFINED_VALUE)
601  {
602  printf("put lToggleEnt\n");
603  print_statement(newStat);
604  hash_put(gLoopToToggleEnt, newStat, gen_copy_seq(lToggleEnt));
605  }
606 
607  lStats = CONS(STATEMENT, newStat, NIL);
608 
609  if(!gGenHRE)
610  {
612  }
613  }
614  // else if the new body is not undefined, then just create a loop without
615  // loop tiling
616  else if(newBody != statement_undefined)
617  {
618  // If there are some unsupported references, then let us add some
619  // statements to the code to support them
620  if(lUnSupportedRef != NIL)
621  {
622  // Let us do what needs to be done to handle the references list
623  if(gGenHRE)
624  {
625  if(!COM_OPT)
626  {
627  process_replacement_HRE(lUnSupportedRef, expression_undefined, &newBody);
628  }
629 
630  newBody = generate_stat_from_ref_list_HRE(lUnSupportedRef, newBody);
631  }
632  else
633  {
634  list lToggleEnt = hash_get(gLoopToToggleEnt,
635  loop_body(statement_loop(stat)));
636 
637  if(lToggleEnt == HASH_UNDEFINED_VALUE)
638  {
639  lToggleEnt = NIL;
640  }
641 
642  newBody = generate_stat_from_ref_list_proc(lUnSupportedRef,
643  lToggleEnt,
644  newBody);
645 
646  fill_gLoopToOpt(lUnSupportedRef);
647  }
648  }
649 
650  // The following lines create the loop
651  loop outerLoop = make_loop(newInnerInd,
652  copy_range(loop_range(curLoop)),
653  newBody,
654  loop_label(curLoop),
656  NIL);
657 
662  make_instruction_loop(outerLoop),NIL,NULL,
664 
665  lStats = CONS(STATEMENT, newStat, NIL);
666 
668  make_reference(loop_index(curLoop), NIL),
669  entity_to_expression(newInnerInd));
670 
671  if(!gGenHRE)
672  {
674  }
675  }
676  else
677  {
678  return make_block_statement(NIL);
679  }
680 
681  if(!gGenHRE)
682  {
683  add_toggle_inc_statements(stat, lStats);
684 
686  }
687 
688  //pips_assert("newStat != statement_undefined",
689  //newStat != statement_undefined);
690 
691  // If some references attached to the loop statement but are not
692  // some supported or unsupported references, then let us handle them
693  list lOutRef = hash_get(gStatToRef, stat);
694 
695  if(lOutRef != HASH_UNDEFINED_VALUE)
696  {
697  // Let us do what needs to be done to handle the references list
698  if(gGenHRE)
699  {
700  if(!COM_OPT)
701  {
702  lStats = process_replacement_HRE_OutRef(lOutRef, lStats);
703  }
704 
705  lStats = generate_stat_from_ref_list_HRE_list(lOutRef, lStats);
706  }
707  else
708  {
709  lStats = generate_stat_from_ref_list_proc_list(lOutRef, lStats);
710 
711  fill_gLoopToOpt(lOutRef);
712  }
713  }
714 
715  // Add some bubbles in the pipeline if needed
716  if(gGenHRE)
717  {
718  lStats = process_gLoopToSync_HRE(stat, lStats);
719 
720  //fill_gLoopToOpt(!NIL);
721  }
722  else
723  {
724  lStats = process_gLoopToSync_proc(stat, lStats);
725 
726  //fill_gLoopToOpt(!NIL);
727  }
728 
729  if(!gGenHRE)
730  {
731  hash_table_free(htOffset);
732  }
733 
734  // Remove the loop statement to the current loops list
735  gen_remove(&glCurLoop, stat);
736 
737  statement newStat = make_block_statement(lStats);
738 
739  printf("newStat real\n");
740  if(newStat == statement_undefined)
741  {
742  printf("newStat == statement_undefined\n");
743  }
744  else
745  {
746  print_statement(newStat);
747  }
748 
749  hash_put(gIsNewLoop, newStat, (void *)true);
750 
751  return newStat;
752 }
753 
754 /*
755 This function add to references list lInRef the supported references of
756 the loop statement stat
757  */
758 static void process_ref_lists(statement stat, list * lInRef)
759 {
760  list lRef = NIL;
761 
762  lRef = hash_get(gLoopToSupRef, stat);
763 
764  if(lRef == HASH_UNDEFINED_VALUE)
765  {
766  lRef = NIL;
767  }
768 
769  MAP(REFERENCE, curRef,
770  {
771  bool bInRef = false;
772 
773  MAP(REFERENCE, supRef,
774  {
775  if(reference_equal_p(curRef, supRef))
776  {
777  bInRef = true;
778  break;
779  }
780  }, lRef);
781 
782  if(bInRef)
783  {
784  *lInRef = CONS(REFERENCE, curRef, *lInRef);
785  }
786 
787  }, glCurRep);
788 
789  MAP(REFERENCE, curRef,
790  {
791  gen_remove(&glCurRep, curRef);
792  }, *lInRef);
793 }
794 
795 /*
796 This function replaces the old references by the HRE private references
797 for a call statement
798  */
799 static void process_opt_replace(statement * newStat)
800 {
801  MAP(STATEMENT, loopStat,
802  {
803  list lIn = NIL;
804 
805  process_ref_lists(loopStat, &lIn);
806 
807  entity curNewInd = hash_get(gHtCurNewInd, loopStat);
808 
809  pips_assert("curNewInd != HASH_UNDEFINED_VALUE",
810  curNewInd != HASH_UNDEFINED_VALUE);
811 
812  expression indExp = entity_to_expression(curNewInd);
813 
814  process_replacement_HRE(lIn, indExp, newStat);
815 
816  free_expression(indExp);
817 
818  gen_free_list(lIn);
819 
820  }, glCurLoop);
821 
823 
825 
827  glCurRep = NIL;
828 }
829 
830 /*
831 This function replaces the old references by the HRE private references
832 for block statement
833  */
834 static list replace_glCurRep_in_seq(list lStats, list lPrevSeq, list lSeq)
835 {
836  list newLStats = NIL;
837 
838  if(lStats == NIL)
839  {
840  return lSeq;
841  }
842 
843  statement newStat = make_block_statement(lStats);
844 
845  process_opt_replace(&newStat);
846 
847  newLStats = CONS(STATEMENT, newStat, NIL);
848 
849  if(lPrevSeq != NIL)
850  {
851  CDR(lPrevSeq) = newLStats;
852  }
853  else
854  {
855  lSeq = newLStats;
856  }
857 
858  return lSeq;
859 }
860 
861 /*
862 This function generates the MMCD code or the HRE code from a block
863 statement.
864  */
866 {
867  statement newStat = statement_undefined;
868 
869  instruction instr = statement_instruction(stat);
870 
871  list lSeq = NIL;
872  list lTempSeq = NIL;
873  list lPrevSeq = NIL;
874 
875  //printf("generate_code_seq\n");
876 
877  // Go through each statement of the sequence
878  MAP(STATEMENT, curStat,
879  {
880  if((COM_OPT && gGenHRE)&& !statement_call_p(curStat) &&
881  !statement_test_p(curStat))
882  {
883  lSeq = replace_glCurRep_in_seq(lTempSeq, lPrevSeq, lSeq);
884 
885  lTempSeq = NIL;
886  }
887 
888  // Let us get the new statement for the current sequence statement
889  statement seqNewStat = generate_code_function(curStat, true);
890 
891  if(seqNewStat != statement_undefined)
892  {
893  list newStatCons = CONS(STATEMENT, seqNewStat, NIL);
894 
895  lSeq = gen_nconc(lSeq, newStatCons);
896 
897  if((COM_OPT && gGenHRE)&&!statement_call_p(curStat) &&
898  !statement_test_p(curStat))
899  {
900  lPrevSeq = newStatCons;
901  }
902 
903  if((COM_OPT && gGenHRE)&&(lTempSeq == NIL) &&
904  (statement_call_p(curStat) ||
905  statement_test_p(curStat)))
906  {
907  lTempSeq = newStatCons;
908  }
909  }
910 
912 
913  if(COM_OPT && gGenHRE)
914  {
915  lSeq = replace_glCurRep_in_seq(lTempSeq, lPrevSeq, lSeq);
916  }
917 
918  if(lSeq == NIL)
919  {
920  newStat = statement_undefined;
921  }
922  else if(gen_length(lSeq) == 1)
923  {
924  newStat = STATEMENT(CAR(lSeq));
925  }
926  else
927  {
928  newStat = make_block_statement(lSeq);
929  }
930 
931  return newStat;
932 }
933 
934 /*
935 This function generate an execute mmcd statement and create a block statement
936 with this new statement and statement stat.
937  */
939 {
940  statement mmcdStat = make_exec_mmcd();
941 
942  statement stepStat = make_step_inc_statement(1);
943 
944  mmcdStat = make_block_statement(gen_nconc(CONS(STATEMENT, stepStat, NIL),
945  CONS(STATEMENT, mmcdStat, NIL)));
946 
947  if(glCurLoop != NIL)
948  {
949  statement loopStat = STATEMENT(CAR(glCurLoop));
950 
951  list lUnSupportedRef = hash_get(gLoopToUnSupRef, loopStat);
952 
953  pips_assert("lUnSupportedRef != HASH_UNDEFINED_VALUE",
954  lUnSupportedRef != HASH_UNDEFINED_VALUE);
955 
956  if(lUnSupportedRef == NIL)
957  {
958  loop curLoop = statement_loop(loopStat);
959 
960  entity newInd = hash_get(gHtCurNewInd, loopStat);
961 
963  entity_to_expression(newInd),
965  NULL);
966 
967  expression neExp =
969  neArg));
970 
971  test t = make_test(neExp, mmcdStat, make_empty_statement());
972 
973  mmcdStat = make_statement(entity_empty_label(),
978  NIL,NULL,
980  }
981  }
982 
983  if(stat == statement_undefined)
984  {
985  return mmcdStat;
986  }
987  else
988  {
990  CONS(STATEMENT, mmcdStat, NIL)));
991  }
992 }
993 
994 /*
995 This function generates the MMCD code or the HRE code from a call
996 statement.
997  */
998 static statement generate_code_call(statement stat, bool bCalledFromSeq)
999 {
1000  //printf("generate_code_call\n");
1001  //print_statement(stat);printf("\n");
1002  statement newStat = statement_undefined;
1003 
1004  if(gGenHRE)
1005  {
1006  newStat = get_call_stat_HRE(stat);
1007  }
1008  else
1009  {
1010  newStat = get_call_stat_proc(stat);
1011  }
1012 
1013  if(COM_OPT && gGenHRE)
1014  {
1015  list lCallRef = NIL;
1016  call curCall = instruction_call(statement_instruction(stat));
1017 
1018  MAP(EXPRESSION, exp,
1019  {
1020  list old = lCallRef;
1021  list new = NIL;
1023 
1024  lCallRef = gen_concatenate(old, new);
1025 
1026  gen_free_list(old);
1027  gen_free_list(new);
1028 
1029  }, call_arguments(curCall));
1030 
1031  glCurRep = gen_nconc(glCurRep, lCallRef);
1032 
1033  if(!bCalledFromSeq)
1034  {
1035  process_opt_replace(&newStat);
1036  }
1037  }
1038 
1039  if(!get_bool_property("COMENGINE_CONTROL_IN_HRE")
1040  && !gGenHRE && !gExecPut)
1041  {
1042  newStat = add_exec_mmcd(newStat);
1043 
1044  gExecPut = true;
1045  }
1046 
1047  if(get_bool_property("COMENGINE_CONTROL_IN_HRE") &&
1048  !gExecPut)
1049  {
1050  statement stepStat;
1051 
1052  if(gGenHRE)
1053  {
1054  stepStat = make_wait_step_statement();
1055  }
1056  else
1057  {
1058  stepStat = make_step_inc_statement(1);
1059  }
1060 
1061  if(newStat == statement_undefined)
1062  {
1063  newStat = stepStat;
1064  }
1065  else
1066  {
1067  newStat =
1069  CONS(STATEMENT, newStat, NIL)));
1070  }
1071 
1072  gExecPut = true;
1073  }
1074 
1075  list lRef = hash_get(gStatToRef, stat);
1076 
1077  if(lRef == HASH_UNDEFINED_VALUE)
1078  {
1079  return newStat;
1080  }
1081 
1082  if(gGenHRE)
1083  {
1084  if(!COM_OPT)
1085  {
1087  }
1088 
1089  newStat = generate_stat_from_ref_list_HRE(lRef, newStat);
1090  }
1091  else
1092  {
1093  newStat = generate_stat_from_ref_list_proc(lRef, NIL, newStat);
1094 
1095  fill_gLoopToOpt(lRef);
1096  }
1097  printf("generate_code_call 2\n");
1098  return newStat;
1099 }
1100 
1101 /*
1102 This functions handles the references that have been attached to the
1103 g_externalized_code during the analysis phase
1104  */
1106 {
1107  list lRef = hash_get(gStatToRef, stat);
1108 
1109  if(lRef == HASH_UNDEFINED_VALUE)
1110  {
1111  return newStat;
1112  }
1113 
1114  if(gGenHRE)
1115  {
1116  if(!COM_OPT)
1117  {
1119  }
1120 
1121  newStat = generate_stat_from_ref_list_HRE(lRef, newStat);
1122  }
1123  else
1124  {
1125  newStat = generate_stat_from_ref_list_proc(lRef, NIL, newStat);
1126 
1127  fill_gLoopToOpt(lRef);
1128  }
1129 
1130  return newStat;
1131 }
1132 
1133 /*
1134 This function generates the MMCD code or the HRE code from any
1135 statements.
1136  */
1137 statement generate_code_function(statement stat, bool bCalledFromSeq)
1138 {
1139  statement newStat = statement_undefined;
1140 
1141  instruction instr = statement_instruction(stat);
1142 
1143  switch(instruction_tag(instr))
1144  {
1146  {
1147  newStat = generate_code_seq(stat);
1148 
1149  break;
1150  }
1151  case is_instruction_loop:
1152  {
1153  newStat = generate_code_loop(stat);
1154  break;
1155  }
1156  case is_instruction_call:
1157  {
1158  newStat = generate_code_call(stat, bCalledFromSeq);
1159  break;
1160  }
1161  case is_instruction_test:
1162  {
1163  if(gGenHRE)
1164  {
1165  newStat = generate_code_test_HRE(stat);
1166  }
1167  else
1168  {
1169  newStat = generate_code_test_proc(stat);
1170  }
1171  break;
1172  }
1173  default:
1174  {
1175  pips_assert("FALSE", false);
1176  break;
1177  }
1178  }
1179 
1180  return newStat;
1181 }
1182 
1183 /*
1184 This function generates the MMCDs generation code and
1185 the HRE code if we want to have only one process on the HRE
1186  */
1188 {
1189  statement newStat = statement_undefined;
1190 
1191  // Initialize some global variables
1192  COM_OPT = true;
1193  gExecPut = false;
1196  glCurLoop = NIL;
1197  glCurRep = NIL;
1199  glOutEffStats = NIL;
1201 
1202  // Do the job
1203  newStat = generate_code_function(stat, false);
1204 
1205  if(statement_block_p(stat))
1206  {
1207  newStat = process_code_seq(newStat, stat);
1208  }
1209 
1210  // Add the loop indices statements
1211  if(glOutEffStats != NIL)
1212  {
1213  newStat =
1215  glOutEffStats));
1216  }
1217 
1218  // Add the toggle initialization statements
1219  if(glToggleInitStats != NIL)
1220  {
1221  newStat =
1223  CONS(STATEMENT, newStat, NIL)));
1224  }
1225 
1226  // Free some global variables
1230 
1231  return newStat;
1232 }
1233 
instruction make_instruction_loop(loop _field_)
Definition: ri.c:1175
execution make_execution(enum execution_utype tag, void *val)
Definition: ri.c:838
call make_call(entity a1, list a2)
Definition: ri.c:269
range copy_range(range p)
RANGE.
Definition: ri.c:2005
loop make_loop(entity a1, range a2, statement a3, entity a4, execution a5, list a6)
Definition: ri.c:1301
basic make_basic(enum basic_utype tag, void *val)
Definition: ri.c:155
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
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
void free_expression(expression p)
Definition: ri.c:853
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
synchronization make_synchronization_none(void)
Definition: ri.c:2424
range make_range(expression a1, expression a2, expression a3)
Definition: ri.c:2041
@ INT
Definition: atomic.c:48
hash_table gIsNewLoop
hash_table gLoopToToggleEnt
hash_table gLoopToSupRef
hash_table gStatToRef
hash_table gRefToFifoOff
expression gBufferSizeEnt
hash_table gLoopToRef
comEngine_distribute.c
hash_table gRefToFifo
hash_table gToggleToInc
hash_table gStatToHtOffset
hash_table gLoopToUnSupRef
list comEngine_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...
statement make_wait_step_statement()
list make_loop_lStats_HRE(statement stat, entity transferSize, statement innerStat, entity newOuterInd, _UNUSED_ list lSupportedRef, _UNUSED_ hash_table htOffset, expression bufferSizeExp)
void get_supportedRef_HRE(statement stat, list *lSupportedRef, list *lUnSupportedRef)
statement get_call_stat_HRE(statement stat)
list process_gLoopToSync_HRE(statement stat, list lInStats)
statement generate_stat_from_ref_list_HRE(list lRef, statement stat)
list generate_stat_from_ref_list_HRE_list(list lRef, list lInStats)
statement generate_code_test_HRE(statement stat)
void process_replacement_HRE(list lRef, expression buffIndExp, statement *stat)
list process_replacement_HRE_OutRef(list lRef, list lStats)
static statement generate_code_loop(statement stat)
static list glCurLoop
entity comEngine_make_new_scalar_variable(const char *prefix, basic bas)
static statement generate_code_call(statement stat, bool bCalledFromSeq)
static void process_opt_replace(statement *newStat)
list glToggleInitStats
static bool gExecPut
static void fill_gLoopToToggleEnt(statement stat, list lRef)
static list glCurRep
static list glOutEffStats
statement comEngine_generate_code(statement stat)
static hash_table gHtCurNewInd
hash_table gLoopToOuterInd
comEngine_generate_code.c
static statement usual_loop_tiling(statement stat, statement newBody, list lSupportedRef, list lUnSupportedRef, hash_table htOffset, expression bufferSizeExp, entity newOuterInd, entity newInnerInd)
static void update_toggle_init_stats_list(statement stat)
statement generate_code_function(statement stat, bool bCalledFromSeq)
static void fill_gLoopToOpt(list lRef)
statement make_toggle_init_statement(entity toggleEnt)
static statement make_loopStat1(statement stat, entity transferSize, statement innerStat, entity newOuterInd, list lSupportedRef, hash_table htOffset, expression bufferSizeExp, entity newInnerInd)
static list replace_glCurRep_in_seq(list lStats, list lPrevSeq, list lSeq)
statement make_toggle_inc_statement(entity toggleEnt, int val)
static void process_ref_lists(statement stat, list *lInRef)
static statement process_code_seq(statement newStat, statement stat)
static void add_toggle_inc_statements(statement stat, list lInStats)
static statement add_exec_mmcd(statement stat)
bool gGenHRE
static statement generate_code_seq(statement stat)
static bool COM_OPT
void comEngine_replace_reference_in_stat(statement stat, reference ref, expression new)
list generate_stat_from_ref_list_proc_list(list lRef, list lInStats)
statement make_toggle_mmcd(entity ent)
list process_gLoopToSync_proc(statement stat, list lInStats)
statement get_call_stat_proc(_UNUSED_ statement stat)
statement make_init_newInd_stat(statement stat, entity newInd)
list add_index_out_effect_proc(loop curLoop, list lStats)
statement generate_stat_from_ref_list_proc(list lRef, list lToggleEnt, statement stat)
statement make_step_inc_statement(int incNum)
list make_loop_lStats_proc(statement stat, entity transferSize, statement innerStat, entity newOuterInd, list lSupportedRef, hash_table htOffset, expression bufferSizeExp)
void create_realFifo_proc(statement stat, list lRef)
void process_innerStat1_proc(statement stat, entity oldInd, entity newOuterInd, entity newInnerInd)
statement make_exec_mmcd()
statement generate_code_test_proc(statement stat)
hash_table gLoopToOpt
cproto-generated files
statement comEngine_opt_loop_interchange(statement stat, statement innerStat, entity newInd)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
list gen_make_list(int domain,...)
Definition: list.c:851
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_concatenate(const list l1x, const list l2x)
concatenate two lists.
Definition: list.c:436
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
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
bool statement_test_p(statement)
Definition: statement.c:343
bool statement_call_p(statement)
Definition: statement.c:364
bool statement_loop_p(statement)
Definition: statement.c:349
statement make_assign_statement(expression, expression)
Definition: statement.c:583
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56
#define UU
Definition: newgen_types.h:98
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
static const char * prefix
#define C_MODULO_OPERATOR_NAME
#define statement_block_p(stat)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define empty_comments
Empty comments (i.e.
#define C_EQUAL_OPERATOR_NAME
#define make_empty_statement
An alias for make_empty_block_statement.
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
entity entity_empty_label(void)
Definition: entity.c:1105
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
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
void AddEntityToCurrentModule(entity)
Add a variable entity to the current module declarations.
Definition: variable.c:260
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 loop_body(x)
Definition: ri.h:1644
@ is_basic_int
Definition: ri.h:571
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
#define range_upper(x)
Definition: ri.h:2290
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define sequence_statements(x)
Definition: ri.h:2360
#define instruction_sequence(x)
Definition: ri.h:1514
#define loop_label(x)
Definition: ri.h:1646
#define range_lower(x)
Definition: ri.h:2288
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define loop_range(x)
Definition: ri.h:1642
@ is_execution_sequential
Definition: ri.h:1189
#define call_arguments(x)
Definition: ri.h:711
#define loop_index(x)
Definition: ri.h:1640
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
char * strdup()
int printf()
#define intptr_t
Definition: stdint.in.h:294
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207