PIPS
sequence_gcm_cse.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sequence_gcm_cse.c 23495 2018-10-24 09:19:47Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /*
28  Global code motion and Common subexpression elimination for nested
29  sequences (a sort of perfect loop nest).
30 */
31 
32 /* option:
33  - whether to push the procedure statement (default no).
34  - whether to do ICM or not directly (default yes).
35  */
36 /* #define PUSH_BODY */
37 /* #define NO_ICM */
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 
42 #include "linear.h"
43 
44 #include "genC.h"
45 #include "ri.h"
46 #include "effects.h"
47 #include "ri-util.h"
48 #include "prettyprint.h"
49 #include "effects-util.h"
50 #include "text-util.h"
51 
52 #include "misc.h"
53 #include "properties.h"
54 
55 #include "resources.h"
56 #include "pipsdbm.h"
57 
58 #include "effects-generic.h"
59 #include "effects-simple.h"
60 
61 #include "expressions.h"
62 
63 #include "eole_private.h"
64 
65 /***************************************** COMMUTATIVE ASSOCIATIVE OPERATORS */
66 
67 /* List of associative and commutative n-ary operators */
68 static char * table_of_AC_operators[] =
78  NULL
79 };
80 
82 {
83  const char* local_name = entity_local_name(e);
84  int i = 0;
85 
86  while (table_of_AC_operators[i])
87  {
89  pips_debug(3," %s is Associative Commutative \n", local_name);
90  return true;
91  }
92  i++;
93  }
94  pips_debug(3," %s is NOT Associative Commutative \n", local_name);
95  return false;
96 }
97 
98 
99 /*********************************************************** ICM ASSOCIATION */
100 
101 /* assumes:
102  - cumulated effects (as a dependence abstraction).
103  - proper effects for statements AND sub-expressions...
104  */
105 
106 /* current nesting of code, bottom-up order, to determine level.
107  */
108 static list nesting = NIL;
109 
110 /* statement stack to current statement.
111  */
113 
114 /* statements to be inserted as a sequence.
115  */
117 
118 /* For CSE */
121 
122 /* PDSon: w_effect store all the variables modified
123  * in the sequence of statement
124  */
125 static list *w_effects;
126 
127 /* Keep track of statement nesting.
128  */
129 static void push_nesting(statement s)
130 {
131  nesting = CONS(STATEMENT, s, nesting);
132 }
133 
134 /* Pop the current statement from nesting list. */
135 static void pop_nesting(statement s)
136 {
137  list old = nesting;
138  pips_assert("same ", nesting && (s == STATEMENT(CAR(nesting))));
139  nesting = CDR(nesting);
140  CDR(old) = NIL;
141  gen_free_list(old);
142 }
143 
144 /* The nesting depth of the current statement */
145 static int current_level(void)
146 {
147  return gen_length(nesting);
148 }
149 
150 /* There is a side effect if there is a W effect in the expression.
151  */
153 {
154  pips_debug(1,"considering expression %s\n",expression_to_string(e));
156  list /* of effect */ le = effects_effects(ef);
157  FOREACH(EFFECT, ef,le)
158  if (effect_write_p(ef)) {
159  pips_debug(1,"has side effects\n");
160  return true;
161  }
162  pips_debug(1,"does not have side effects\n");
163  return false;
164 }
165 
166 /* Compute if an effect list Some effect in les interfere with var.
167 
168  @param[in] var is the variable to test interference with the effects
169 
170  @param[in] les is the effect list to look for var
171 
172  @return true if there may be a write effect on var
173  */
174 static bool interference_on(entity var, list /* of effect */ les)
175 {
176  FOREACH(EFFECT, ef, les) {
177  /* There is an interference only if there is a write effect: */
178  if (effect_write_p(ef)) {
180  /* If an effect can write anywhere, it may be also on var: */
181  return true;
182 
184  /* If we may have a write effect on var, mark a conflict: */
185  return true;
186  }
187  }
188  return false;
189 }
190 
191 
192 /* Whether sg with effects le can be moved up to s.
193  */
194 static bool moveable_to(list /* of effects */ le, statement s)
195 {
197  FOREACH(EFFECT, ef,le)
199  return false;
200  return true;
201 }
202 
203 /* Return the level of this expression, using the current nesting list.
204  * 0: before any statement!
205  * n: outside nth loop.
206  * and so on.
207  */
208 static int level_of(list /* of effects */ le)
209 {
210  list /* of statement */ up_nesting = gen_nreverse(gen_copy_seq(nesting));
211  int level = 0;
212  FOREACH(STATEMENT, s,up_nesting)
213  {
214  if (moveable_to(le, s))
215  break;
216  else
217  level++;
218  }
219  gen_free_list(up_nesting);
220  return level;
221 
222 }
223 
224 /* The level can be queried for a sub expression. */
226 {
227  list le;
228  if (!bound_expr_prw_effects_p(e)) {
229  /* try again ! */
231  bool writes = false;
232  FOREACH(EFFECT,eff,le) {
233  if((writes=effect_write_p(eff))) break;
234  }
235  if(writes)
236  return -1; /* assigns... */
237  else {
238  int res = level_of(le);
239  gen_full_free_list(le);
240  return res;
241  }
242  }
243  else {
245  return level_of(le);
246  }
247 }
248 
249 /* or for a statement. */
250 /*
251 static int stat_level_of(statement s)
252 {
253  list le = load_proper_rw_effects_list(s);
254  return level_of(le);
255 }
256 */
257 
258 /* Returns the statement of the specified level
259  should returns current_statement_head() to avoid ICM directly.
260  */
262 {
263 #if !defined(NO_ICM)
264  int n = current_level()-1-level;
265 
266  if (n>=0)
267  return STATEMENT(gen_nth(n, nesting));
268  else
269 #endif
270  return current_statement_head();
271 }
272 
273 /* Test if the current statement is not the top one: */
274 static bool currently_nested_p(void)
275 {
276 #if defined(PUSH_BODY)
277  return current_level()>1;
278 #else
279  return current_level()>0;
280 #endif
281 }
282 
284 {
285  instruction i;
286  call assign;
287  expression right_side;
288 
289  i = statement_instruction(stat);
290 
291  pips_assert("Instruction is a call", instruction_call_p(i));
292  assign = instruction_call(i);
293 
294  pips_assert("Call is an assignment!",
295  ENTITY_ASSIGN_P(call_function(assign)));
296 
297  right_side = EXPRESSION(CAR(CDR(call_arguments(assign))));
298 
299  return right_side;
300 }
301 
302 /* Verify if entity ent is an argument in the right expression
303  * of the assign statement stat
304  */
305 static bool entity_as_arguments(entity ent, statement stat)
306 {
307  expression right_side;
308  call right_call;
309 
310  right_side = right_side_of_assign_statement(stat);
311 
312  pips_assert("Right expression is a call!",
313  syntax_call_p(expression_syntax(right_side)));
314  right_call = syntax_call(expression_syntax(right_side));
315 
316  FOREACH(EXPRESSION, e,call_arguments(right_call))
317  {
318  syntax s = expression_syntax(e);
319  /* Argument is maybe a call to a constant */
320  if (syntax_reference_p(s) &&
322  {
323  return true;
324  }
325  }
326 
327  return false;
328 }
329 
330 /* Return the expression in the left side of an assign statement
331  */
333 {
334  if (assignment_statement_p(stat))
335  {
337  return EXPRESSION(CAR(call_arguments(assign)));
338  }
339 
340  pips_internal_error("It is not an assign statement !");
341 
342  return NULL;
343 }
344 
345 /* Return the entity in left side of an assign statement
346  */
348 {
350  if( ! syntax_reference_p(expression_syntax(left_side)) )
351  return entity_undefined;
352  else
354 }
355 
356 /* Insert statement s in the list of statement l
357  */
359 {
361  statement s = STATEMENT(CAR(l));
362 
363  if (entity_undefined_p(ent) || entity_as_arguments(ent, s) || ENDP(CDR(l)) )
364  {
365  return CONS(STATEMENT, s, CONS(STATEMENT, news, CDR(l)));
366  }
367  return CONS(STATEMENT, s,
369 }
370 
371 /* Just for test
372 static void dump_list_of_statement(list l)
373 {
374  fprintf(stderr, "\n===== Dump List: \n");
375  MAP(STATEMENT, ss,
376  {
377  print_statement(ss);
378  }, l);
379  fprintf(stderr, "\n END dumpt List!!! \n");
380 }
381 */
382 
383 static void insert_before_statement(statement news, statement s, bool last)
384 {
386  if (!bound_inserted_p(s))
387  {
388  store_inserted(s, make_block_statement(CONS(STATEMENT, news, NIL)));
389  }
390  else
391  {
392  statement sb = load_inserted(s);
394 
396 
397  /* Statements are stored in reverse order...
398  this will have to be fixed latter on. see #1#.
399  */
400 
401  /* Insert in the front of list
402  * ===========================
403  */
404  if (last)
405  {
407  }
408  /* Insert just before the appropriate statement of list
409  * ====================================================
410  */
411  else
412  {
413  instruction_block(i) =
415  }
416  }
417 }
418 
419 /* Atomizable if some computation.
420  */
422 {
423  syntax s = expression_syntax(e);
424  switch (syntax_tag(s))
425  {
426  case is_syntax_range:
427  case is_syntax_reference:
428  return false;
429  case is_syntax_call:
430  {
431  entity called = call_function(syntax_call(s));
432  /* Missing cases? user functions? I/O? */
433  return !entity_constant_p(called) && !ENTITY_IMPLIEDDO_P(called);
434  }
435  default:
436  pips_internal_error("unexpected syntax tag: %d", syntax_tag(s));
437  return false;
438  }
439 }
440 
441 static gen_array_t /* of list of expressions */
442 group_expr_by_level(int nlevels, list le)
443 {
444  gen_array_t result = gen_array_make(nlevels+1);
445  int i;
446  bool first_alone;
447 
448  /* initialize chunks. */
449  for (i=0; i<=nlevels; i++)
450  gen_array_addto(result, i, list_undefined);
451 
452  /* put expressions in chunks. */
453  FOREACH(EXPRESSION, e,le)
454  {
455  int elevel = expr_level_of(e);
456  list eatlevel;
457  pips_assert("coherent level", elevel>=0 && elevel<=nlevels);
458 
459  if (side_effects_p(e))
460  {
461  elevel = nlevels;
462  }
463 
464  eatlevel = (list) gen_array_item(result, elevel);
465  if (eatlevel == list_undefined)
466  {
467  eatlevel = CONS(EXPRESSION, e, NIL);
468  }
469  else
470  {
471  eatlevel = CONS(EXPRESSION, e, eatlevel);
472  }
473  gen_array_addto(result, elevel, eatlevel);
474  }
475 
476  /* Fix expressions by useful levels, with some operations.
477  */
478  first_alone = true;
479  for (i=0; i<nlevels && first_alone; i++)
480  {
481  list lei = (list) gen_array_item(result, i);
482  if (lei != list_undefined)
483  {
484  int lenlei = gen_length(lei);
485  if (lenlei == 1)
486  {
487  list next = (list) gen_array_item(result, i+1);
488  if (next == list_undefined)
489  next = lei;
490  else
491  next = gen_nconc(next, lei);
492  gen_array_addto(result, i+1, next);
493  gen_array_addto(result, i, list_undefined);
494  }
495  else
496  first_alone = false;
497  }
498  }
499 
500  return result;
501 }
502 
503 #if 0
504 static void print_group_expr(gen_array_t /* array of group of expressions */ g
505  , int nombre_grp)
506 {
507  int i;
508  for(i=0; i<= nombre_grp; i++)
509  {
510  list l = (list)gen_array_item(g, i);
511  fprintf(stderr,"\n\n***GROUP LEVEL %d:\n", i);
512  if (l)
513  {
514  MAP(EXPRESSION, e,
515  {
516  fprintf(stderr,"; ");
518  },
519  l);
520  }
521  }
522 }
523 #endif
524 
525 /* Atomize sub expressions with
526  - lower level
527  - not simple (references or constants)
528  - no side effects.
529 */
531 {
532  int elevel = expr_level_of(e);
533 
534  pips_debug(1,"considering expression %s\n",expression_to_string(e));
535  if (elevel!=-1 &&
536  elevel<level &&
538  !side_effects_p(e))
539  {
540  pips_debug(1,"atomize \n");
542  if (atom)
544  }
545  else
546  pips_debug(1,"not atomize\n");
547 }
548 
549 
550 static void atomize_call(call c, int level)
551 {
552  list /* of expression */ args;
553  int lenargs;
554 
555  args = call_arguments(c);
556  lenargs = gen_length(args);
557 
558  if (lenargs>=2)
559  {
560  FOREACH(EXPRESSION, sube, args)
562  }
563 }
564 
565 
567 {
568  syntax syn;
569  call c;
570  entity func;
571  list /* of expression */ args;
572  int lenargs;
573 
574  /* Some depth, otherwise no ICM needed!
575  * should be fixed if root statement is pushed?
576  */
577  if (!currently_nested_p()) return;
578 
579 
580  syn = expression_syntax(e);
581 
582  /* skip casts */
584 
585  /* Only do something with calls */
586  if (!syntax_call_p(syn))
587  return;
588 
589  pips_debug(1,"considering expression %s\n",expression_to_string(e));
590 
591  /* something to icm
592  */
593  c = syntax_call(syn);
594  func = call_function(c);
595  args = call_arguments(c);
596  lenargs = gen_length(args);
597 
598  if (Is_Associative_Commutative(func) && lenargs>2)
599  {
600  /* Reassociation + atomization maybe needed.
601  * code taken from JZ.
602  */
603  int i, nlevels = current_level();
604  gen_array_t groups = group_expr_by_level(nlevels, args);
605  list lenl;
606 
607  /* Note: the last level of an expression MUST NOT be moved!
608  * indeed, there may be a side effects in another part of the expr.
609  */
610  for (i=0; i<nlevels; i++)
611  {
612  list lei = (list) gen_array_item(groups, i);
613  if (lei!=list_undefined)
614  {
615  int j;
616  bool satom_inserted = false;
617  syntax satom = make_syntax_call(make_call(func, lei));
619  statement atom;
620 
621  /* Insert expression in upward expression, eventually in e!
622  */
623  for (j=i+1; j<=nlevels && !satom_inserted; j++)
624  {
625  list lej = (list) gen_array_item(groups, j);
626  if (lej!=list_undefined)
627  {
628  eatom = make_expression(satom, normalized_undefined);
629  lej = CONS(EXPRESSION, eatom, lej);
630  gen_array_addto(groups, j, lej);
631  satom_inserted = true;
632  }
633  }
634  if (!satom_inserted)
635  {
636  expression_syntax(e) = satom;
637  eatom = e;
638  }
639 
642  }
643  }
644 
645  /* Fix last level if necessary.
646  */
647  lenl = (list) gen_array_item(groups, nlevels);
648  if (lenl != list_undefined)
649  call_arguments(c) = lenl;
650  }
651  else
652  {
653  atomize_call(c, level);
654  }
655 }
656 
657 /* Don't go into I/O calls... */
658 static bool icm_atom_call_flt(call c)
659 {
660  entity called = call_function(c);
661  return !(io_intrinsic_p(called) || ENTITY_IMPLIEDDO_P(called));
662 }
663 
664 /* Atomize an instruction with call
665 
666  Maybe I could consider moving the call as a whole?
667  */
669 {
670  if (!currently_nested_p())
671  /* Since we are at the top level statement, impossible to move
672  something outside... */
673  return;
674 
675  if (!instruction_call_p(i))
676  /* Should have been dealt by other means in the gen_multi_recurse()
677  from gen_multi_recurse() before */
678  return;
679 
680  /* stat_level_of(current_statement_head())); */
682 }
683 
684 static void atomize_test(test t)
685 {
686  if (!currently_nested_p()) return;
688 }
689 
691 {
692  if (!currently_nested_p()) return;
694 }
695 
697 {
699 }
700 
701 static bool loop_flt(loop l)
702 {
703  statement sofl = current_statement_head();
704  pips_assert("statement of loop",
706  /* RK: Why ? */
707  push_nesting(sofl);
708  return true;
709 }
710 
711 static void loop_rwt(loop l)
712 {
713  range bounds;
714  int level;
715  statement sofl = current_statement_head();
716  /* RK: Why ? */
717  pop_nesting(sofl);
718 
719  /* Deal with loop bound expressions
720  */
721  if (!currently_nested_p())
722  /* Nothing to do if we are in the top-level statement */
723  return;
724  bounds = loop_range(l);
725  level = current_level();
726  /* Atomize the loop bound expressions: */
730 }
731 
732 /* PDSon: I use the field 'comments' of statement for counting its number of
733  * use. Raison: The field 'comments' of new statement added is always empty!
734  * This function verifies if number of use is greater than 1 or not.
735  */
737 {
738  char* comment = statement_comments(s);
739  int number = 0;
740 
742  {
743  return false;
744  }
745 
746  sscanf((const char*)comment,"%d", &number);
747  return (number > 1);
748 }
749 
750 /* Update the field 'comments' of a statement
751  */
752 static void set_comment_of_statement(statement s, char *new_comment)
753 {
755  {
756  statement_comments(s) = new_comment;
757  }
758  else
759  {
761  statement_comments(s) = new_comment;
762  }
763 }
764 
765 /* Update the number of use of statement defining 'ent' which is a member
766  * of list lst_stat with step up_down (up_down = 1 | 0 | -1).
767  * If ent is a variable of original code (ex: x, y), not new variable added
768  * (ex: F_0, F_1,..), there is not any statement in lst_stat defining ent.
769  * Return: statement updated
770  */
771 static statement update_number_of_use(entity ent, list lst_stat, int up_down)
772 {
773  FOREACH(STATEMENT, s,lst_stat)
774  {
775  entity left_side = left_side_of_assign_statement(s);
776  if(ent == left_side) // s defines ent
777  {
778  if (up_down == 0)
779  {
780  return s;
781  }
782 
783  /* First time, no value */
785  {
786  if (up_down == -1)
787  {
788  pips_internal_error("Number of use of '%s' < 0 !!!",
789  entity_name(ent));
790  }
792  }
793  /* Update old value */
794  else
795  {
796  char *new;
797  int number_use = 0;
798  char* comment = statement_comments(s);
799  sscanf((const char*)comment, "%d", &number_use);
800 
801  number_use += up_down;
802  new=int2a(number_use);
803  set_comment_of_statement(s, (new));
804  }
805  return s;
806  }
807  }
808 
809  return NULL;
810 }
811 
812 /* Increase number of use of variable ent by one */
813 static void increase_number_of_use_by_1(entity ent, statement container)
814 {
815  if (bound_inserted_p(container))
816  {
817  statement updated, sblock = load_inserted(container);
819  sequence seq;
820  int step;
822 
823  seq = instruction_sequence(i);
824 
825  step = +1;
826  if(assignment_statement_p(container))
827  {
828  if (ent == left_side_of_assign_statement(container))
829  {
830  step = 0;
831  }
832  }
833 
834  if (!(updated = update_number_of_use(ent, sequence_statements(seq), step)))
835  {
836  pips_internal_error("No statement defines '%s'", entity_name(ent));
837  }
838 
839  /* Reduce by 1 number of use of variables contained by statement Updated */
840  {
843  {
845  FOREACH(EXPRESSION, arg,args)
846  {
847  syntax syn = expression_syntax(arg);
848  if(syntax_reference_p(syn))
849  {
852  }
853  }
854  }
855  }
856  }
857  else
858  {
859  pips_internal_error("No statement inserted!");
860  }
861 }
862 
863 static void remove_statement_redundant(statement s, list* inserted);
864 
865 static bool cse_expression_flt(expression e, list* inserted)
866 {
867  pips_debug(2,"examining expression:");
868  ifdebug(2) { print_expression(e); }
869  entity scala;
870 
872  {
873  /* Go down */
874  return true;
875  }
876 
878  FOREACH(STATEMENT, s,*inserted)
879  {
881  if (scala == ent)
882  {
884  {
885  /* This statement is a real one. But it maybe contains a variable
886  * temporal -> Continue remove redundant statement from this one
887  */
888  remove_statement_redundant(s, inserted);
889 
890  /* Remove its comment for pretty look: It is visited! Not do again! */
892 
893  /* Go up */
894  return false;
895  }
897  {
898  /* This statement is already visited! Not do again! Go up */
899  return false;
900  }
901  else
902  {
903  pips_debug(1,"redundant statement purged:\n");
904  ifdebug(1) { print_statement(s); }
905  /* s is a redundant statement. Replace e by the right side of
906  * the assign statement s
907  */
910  expression_syntax(exp) = NULL;
911 
912  /* Remove s from list
913  */
914  gen_remove_once(inserted, s);
915 
916  free_statement(s);
917 
918  /* Continue go down the new expression */
919  return true;
920  }
921  }
922  }
923 
924  /* Nothing is done! Go up */
925  return false;
926 }
927 #if 1
928 
929 /* Avoid visit the left side of assign statement
930  */
931 static bool cse_call_flt(call c, __attribute__((unused))list* inserted)
932 {
934  {
935  expression lhs = binary_call_lhs(c);
936  if(get_bool_property("COMMON_SUBEXPRESSION_ELIMINATION_SKIP_LHS") || expression_scalar_p(lhs) || expression_pointer_p(lhs) )
937  gen_recurse_stop(lhs);
938  }
939  /* Go down! */
940  return true;
941 }
942 #endif
943 
944 /* Remove statement redundant inserted before statement s
945  */
946 static void remove_statement_redundant(statement s, list* inserted)
947 {
948  gen_context_multi_recurse(s, inserted,
951  NULL);
952 }
953 
954 
955 /* Insert the new statements created
956  */
957 static void insert_rwt(statement s)
958 {
959  if (bound_inserted_p(s))
960  {
961  statement sblock = load_inserted(s);
963  sequence seq;
964 
965  pips_assert("it is a sequence", instruction_sequence_p(i) && entity_empty_label_p(statement_label(sblock)));
966 
967  /* Reverse list of inserted statements (#1#) */
968  seq = instruction_sequence(i);
969 
970  /* Remove statements redundant */
972 
974  /* need some patching */
982 
984  }
985 }
986 
987 static bool prepare_icm(statement s) {
988  if(statement_loop_p(s)) {
989  try_reorder_expressions(s,true);
990  }
991  return true;
992 }
993 
994 /* Perform ICM and association on operators.
995  This is kind of an atomization.
996  many side effects: modifies the code, uses simple effects
997 
998  @param[in] name specified the module name to work on
999 
1000  @param[in,out] s is the statement of the module
1001  */
1002 void perform_icm_association(const char* name, /* of the module */
1003  statement s /* of the module */)
1004 {
1005  pips_assert("clean static structures on entry",
1006  (get_current_statement_stack() == stack_undefined) &&
1007  inserted_undefined_p() &&
1008  (nesting==NIL));
1009 
1010  /*
1011  simple_cumulated_effects(name, s);
1012  set_cumulated_rw_effects(get_rw_effects());
1013  */
1014 
1015  /* GET CUMULATED EFFECTS
1016  */
1018  db_get_memory_resource(DBR_CUMULATED_EFFECTS, name, true));
1019 
1020  /* SG: reorder expression so that the icm algorithm matches more cases */
1022 
1023  /* Set full (expr and statements) PROPER EFFECTS
1024  */
1025  full_simple_proper_effects(name, s);
1026 
1027  /* Initialize the "inserted" mapping: */
1028  init_inserted();
1029  /* Create the stack to track current statement: */
1030  make_current_statement_stack();
1031 
1032 #if defined(PUSH_BODY)
1033  push_nesting(s);
1034 #endif
1035 
1036  /* ATOMIZE and REASSOCIATE by level.
1037  */
1039  /* On each statement, we push the statement top-down
1040  on the current_statement stack, and when climbing
1041  bottom-up, we pull back the statement and verify it
1042  was the same on the stack. Nowadays we could use
1043  statement parent information directly from
1044  NewGen... */
1045  statement_domain, current_statement_filter, current_statement_rewrite,
1046  /* Atomize instructions with calls during bottom-up
1047  phase: */
1049  /* */
1053  /* could also push while loops... */
1055  /* do not atomize index computations at the time... */
1056  //reference_domain, gen_false, gen_null,
1057  call_domain, icm_atom_call_flt, gen_null, /* skip IO calls */
1058  NULL);
1059  /* Insert moved code in statement at the right place: */
1061 
1062 
1063 #if defined(PUSH_BODY)
1064  pop_nesting(s);
1065 #endif
1066 
1067  pips_assert("clean static structure on exit",
1068  (nesting==NIL) &&
1069  (current_statement_size()==0));
1070 
1071  /* Delete the stack used to track current statement: */
1072  free_current_statement_stack();
1073  close_inserted();
1074 
1076 
1077  close_expr_prw_effects(); /* no memory leaks? */
1079 
1080  /* some clean up */
1081  /* This only works in Fortran because of C local declarations. It's
1082  easier to let restructure_control() or flatten_code take care of
1083  it. */
1084  //flatten_sequences(s);
1085 }
1086 
1087 /********************************************************** EXTRACT ENTITIES */
1088 
1089 static list seen = NIL;
1090 
1091 static void add_ref_ent(reference r)
1093 
1094 static void add_call_ent(call c)
1095 { seen = gen_once(call_function(c), seen); }
1096 
1098 {
1099  list result;
1100  seen = NIL;
1101 
1105  NULL);
1106 
1107  result = seen;
1108  seen = NIL;
1109  return result;
1110 }
1111 
1112 /******************************************************************** AC-CSE */
1113 /* performs
1114  Associative-Commutative Common Subexpression Elimination
1115  on sequences.
1116 
1117  reimplements an atomization once more?
1118  should not atomize I/O...
1119 */
1120 
1121 typedef struct
1122 {
1123  entity scalar; /* the entity which holds the value? or partial? */
1124  entity operator; /* NULL for references */
1125  list /* of entity */ depends; /* W effects on these invalidates the scalar */
1126  statement container; /* statement in which it appears (for atomization) */
1127  expression contents; /* call or reference... could be a syntax? */
1128  list available_contents; /* part of which is available */
1129 
1130  /* Added by PDSon:
1131  This list stores variables modified. It is used to avoid of creating
1132  expression common containing variable modified.
1133  It shoud remove membre 'depends'!
1134  It is a pointer into the global list 'w_effects'
1135  */
1136  list *w_effects; /* list of expression */
1137 }
1139 
1140 #if 0
1141 static void dump_aspt(available_scalar_pt aspt)
1142 {
1143  syntax s;
1144 
1145  if (!aspt)
1146  {
1147  fprintf(stderr, "DUMP ASPT\n ASPT = NULL !!!\n");
1148  return;
1149  }
1150 
1151  s = expression_syntax(aspt->contents);
1152  fprintf(stderr,
1153  "DUMP ASPT\n"
1154  "Scalar: %s \t Operator:[%s] len=%d, avail=%d\n",
1155  entity_name(aspt->scalar),
1156  aspt->operator? entity_name(aspt->operator): "NOP",
1159  fprintf(stderr, "\n===Container:\n");
1160  print_statement(aspt->container);
1161  fprintf(stderr, "\n===Contents:\n");
1162  print_expression(aspt->contents);
1163  fprintf(stderr, "\n===Available_contents:\n");
1164  MAP(EXPRESSION, e,
1165  {
1166  print_expression(e);
1167  }, aspt->available_contents);
1168 }
1169 #endif
1170 
1171 static bool try_reorder_expression_call(expression e, list availables) {
1172  /* update normalized field, and make sure it is consistent */
1176  /* the idea is to split an expression into two linear parts, one that is already available and one that is not */
1177  if(normalized_linear_p(n)){
1178  Pvecteur pv =normalized_linear(n);
1179  int cplx =vect_size(pv);
1180  int bestcplx = INT_MAX;
1181  expression bestexp = expression_undefined;
1182  FOREACH(EXPRESSION,eavailable, availables){
1183  NORMALIZE_EXPRESSION(eavailable);
1184  normalized navailable = expression_normalized(eavailable);
1185  if(normalized_linear_p(navailable)) {
1186  Pvecteur pva = normalized_linear(navailable);
1187  Pvecteur diff = vect_substract(pv,pva);
1188  int dcplx = vect_size(diff);
1189  if(dcplx < cplx && dcplx < bestcplx) {
1190  bestexp = eavailable;
1191  bestcplx=dcplx;
1192  }
1193  vect_rm(diff);
1194  }
1195  }
1196  if(!expression_undefined_p(bestexp) && !same_expression_p(e,bestexp)) {
1199  make_call(
1203  copy_expression(e),
1204  copy_expression(bestexp)
1205  ),
1206  copy_expression(bestexp)
1207  )
1208  )
1209  )
1210  );
1211  return false;
1212  }
1213  }
1214  return true;
1215 }
1216 
1217 /* make sure expressions are ordered with pointer first */
1219  if(expression_call_p(e)) {
1220  call c = expression_call(e);
1221  if(commutative_call_p(c)) {
1222  expression lhs = binary_call_lhs(c),
1223  rhs = binary_call_rhs(c);
1224  basic brhs = basic_of_expression(rhs);
1225  if(basic_pointer_p(brhs)) {
1228  rhs,lhs);
1229  }
1230  }
1233  }
1234 }
1235 
1236 static void do_gather_all_expressions_perms(list sterns,list * perms) {
1237  if(ENDP(sterns)) *perms=NIL;
1238  else {
1239  expression head = EXPRESSION(CAR(sterns));
1240  unnormalize_expression(head);
1241  NORMALIZE_EXPRESSION(head);
1242  POP(sterns);
1243  *perms = CONS(EXPRESSION,copy_expression(head),*perms);
1244  list nperms = NIL;
1245  do_gather_all_expressions_perms(sterns,&nperms);
1246  FOREACH(EXPRESSION,exp,nperms) {
1253  *perms=CONS(EXPRESSION,epv,*perms);
1254  }
1255  *perms=gen_nconc(*perms,nperms);
1256  }
1257 }
1258 
1259 static bool do_gather_all_expressions(expression e, list * gathered) {
1262  if(normalized_linear_p(n)) {
1263  Pvecteur pv = normalized_linear(n);
1264  list sterns=NIL;
1265  for(Pvecteur ipv = pv; !VECTEUR_NUL_P(ipv) ; ipv=vecteur_succ(ipv)) {
1267  if(TCST != vecteur_var(ipv)) {
1269  stern,
1271  }
1272  sterns=CONS(EXPRESSION,stern,sterns);
1273  }
1274  list perms = NIL;
1275  do_gather_all_expressions_perms(sterns,&perms);
1276  *gathered=gen_nconc(*gathered,perms);
1277  return false;
1278  }
1279  return true;
1280 }
1281 
1282 static void prune_singleton(list * l) {
1283  list new = NIL;
1284  FOREACH(EXPRESSION,e0,*l) {
1285  FOREACH(EXPRESSION,e1,*l) {
1286  if(e0!=e1 && same_expression_p(e0,e1) ) {
1287  new=CONS(EXPRESSION,copy_expression(e0),new);
1288  break;
1289  }
1290  }
1291  }
1292  gen_full_free_list(*l);
1293  *l=new;
1294 }
1295 
1296 /* whether to get in here, whether to atomize... */
1297 static bool expr_cse_flt(expression e,__attribute__((unused))list *skip_list)
1298 {
1299  pips_debug(2,"considering expression:");
1300  ifdebug(2) print_expression(e);
1301  syntax s = expression_syntax(e);
1302  switch (syntax_tag(s))
1303  {
1304  case is_syntax_call:
1305  return !IO_CALL_P(expression_call(e));
1306  case is_syntax_reference:
1307  //return entity_scalar_p(reference_variable(syntax_reference(s)));
1308  case is_syntax_subscript:
1309  case is_syntax_cast:
1310  return true;
1311  default:
1312  return false;
1313  }
1314 }
1315 
1316 #define NO_SIMILARITY (0)
1317 #define MAX_SIMILARITY (1000)
1318 
1319 #if 0
1320 /* return the entity stored by this function.
1321  should be a scalar reference or a constant...
1322  or a call to an inverse operator.
1323  */
1324 static entity entity_of_expression(expression e, bool * inverted, entity inv)
1325 {
1326  syntax s = expression_syntax(e);
1327  *inverted = false;
1328  switch (syntax_tag(s))
1329  {
1330  case is_syntax_call:
1331  {
1332  call c = syntax_call(s);
1333  if (call_function(c)==inv)
1334  {
1335  *inverted = true;
1336  return entity_of_expression(EXPRESSION(CAR(call_arguments(c))),
1337  inverted, NULL);
1338  }
1339  else
1340  return call_function(c);
1341  }
1342  case is_syntax_reference:
1343  {
1344  reference r = syntax_reference(s);
1345  if (reference_indices(r))
1346  return NULL;
1347  else
1348  return reference_variable(r);
1349  }
1350  case is_syntax_range:
1351  default:
1352  break;
1353  }
1354  return NULL;
1355 }
1356 #endif
1357 
1359 {
1360  MAP(EXPRESSION, f, if (e==f) return true, seen);
1361  return false;
1362 }
1363 
1365 {
1366  FOREACH(EXPRESSION, f,avails)
1368  return f;
1369  return NULL;
1370 }
1371 
1372 static list /* of expression */
1374 {
1375  list already_seen = NIL;
1376 
1377  FOREACH(EXPRESSION, e, args)
1378  {
1379  expression n = find_equal_expression_not_in_list(e, avails, already_seen);
1380  if (n) already_seen = CONS(EXPRESSION, n, already_seen);
1381  }
1382 
1383  return already_seen;
1384 }
1385 
1386 /*
1387 static void dump_list_of_exp(list l)
1388 {
1389  fprintf(stderr,"\n======\nDUMP LIST OF EXPRESSIONS \n");
1390  fprintf(stderr,"Length: %d\n", gen_length(l));
1391  MAP(EXPRESSION, e,
1392  {
1393  print_expression(e);
1394  },
1395  l);
1396 
1397  fprintf(stderr,"\n======\nEND DUMP\n");
1398 }
1399 
1400 static void dump_expresison_nary(expression e)
1401 {
1402  syntax s = expression_syntax(e);
1403  fprintf(stderr,"\n===== DUMP EXPRESSION: \n");
1404  if (syntax_reference_p(s))
1405  {
1406  fprintf(stderr,"\n Reference!!");
1407  }
1408  else if (syntax_call_p(s))
1409  {
1410  fprintf(stderr,"\n Call '%s' with %d arguments \n",
1411  entity_local_name(call_function(syntax_call(s))),
1412  gen_length(call_arguments(syntax_call(s))));
1413  }
1414  fprintf(stderr,"\n===== END DUMP EXPRESSION!! \n");
1415 }
1416 */
1417 
1418 static list /* of expression */
1419 list_diff(list l1, list l2); /* Define forward */
1420 
1421 static bool /* Define forward */
1423 
1424 /* Find the commun sub-expression between e & aspt.
1425  * Attention: Commun expression does't contain any expression in w_effects
1426  */
1428 {
1429  syntax s = expression_syntax(e), sa = expression_syntax(aspt->contents);
1430 
1431  /*
1432  fprintf(stderr, "similarity on %s\n", entity_name(aspt->scalar));
1433  print_expression(e);
1434  dump_aspt(aspt);
1435  */
1436 
1437  if (syntax_tag(s)!=syntax_tag(sa)) return NO_SIMILARITY;
1438 
1439  if (syntax_reference_p(s))
1440  {
1441  reference r = syntax_reference(s), ra = syntax_reference(sa);
1442  if (reference_equal_p(r, ra))
1443  {
1444  return MAX_SIMILARITY;
1445  }
1446  }
1447 
1448  if (syntax_call_p(s))
1449  {
1450  call c = syntax_call(s), ca = syntax_call(sa);
1451  entity cf = call_function(c);
1452  if (cf!=call_function(ca)) return NO_SIMILARITY;
1453 
1454  /* same function...
1455  */
1457  {
1458  /* similarity is the number of args in common.
1459  inversion is not tested at the time.
1460  */
1462  *(aspt->w_effects)),
1463  aspt->available_contents);
1464  size_t n = gen_length(com);
1465  gen_free_list(com);
1466  if (n<=1) return NO_SIMILARITY;
1467  return (n == gen_length(call_arguments(ca)) &&
1468  n == gen_length(call_arguments(c))) ? MAX_SIMILARITY: n;
1469  }
1470  else
1471  {
1472  /* any call: must be equal
1473  */
1474  list l = call_arguments(c), la = call_arguments(ca);
1475  pips_assert("same length", gen_length(l)==gen_length(la));
1476  for (; l; l = CDR(l), la = CDR(la))
1477  {
1478  expression el = EXPRESSION(CAR(l)), ela = EXPRESSION(CAR(la));
1479  if (!expression_equal_p(el, ela))
1480  {
1481  return NO_SIMILARITY;
1482  }
1483 
1484  if (expression_eq_in_list_p(el, *(aspt->w_effects), &el))
1485  {
1486  /* A variable is already modified ! */
1487  return NO_SIMILARITY;
1488  }
1489  }
1490  return MAX_SIMILARITY;
1491  }
1492  }
1493 
1494  return NO_SIMILARITY;
1495 }
1496 
1498 {
1499  available_scalar_pt best = NULL;
1500  (*best_quality) = 0;
1501 
1503  {
1505  int quality = similarity(e, aspt);
1506  if (quality==MAX_SIMILARITY)
1507  {
1508  (*best_quality) = quality;
1509  return aspt;
1510  }
1511  if (quality>0 && (*best_quality)<quality)
1512  {
1513  best = aspt;
1514  (*best_quality) = quality;
1515  }
1516  }
1517 
1518  return best;
1519 }
1520 
1522  statement container,
1523  expression contents)
1524 {
1525  pips_debug(2,"adding new scalar to pool:%s\nas a container for %s\n",
1526  entity_user_name(scalar),expression_to_string(contents));
1527  syntax s = expression_syntax(contents);
1528 
1529  available_scalar_pt aspt =
1531 
1532  aspt->scalar = scalar;
1533  aspt->container = container;
1534  aspt->contents = contents;
1535 
1536  aspt->depends = get_all_entities(contents);
1537 
1538  aspt->w_effects = w_effects;
1539 
1540  if (syntax_call_p(s))
1541  {
1542  call c = syntax_call(s);
1543  aspt->operator = call_function(c);
1546  else
1547  aspt->available_contents = NIL;
1548  }
1549  else
1550  {
1551  aspt->operator = NULL;
1552  aspt->available_contents = NIL;
1553  }
1554 
1555  return aspt;
1556 }
1557 
1559 {
1560  FOREACH(EXPRESSION, et,l)
1561  {
1562  if (expression_equal_p(e, et))
1563  {
1564  *f = et;
1565  return true;
1566  }
1567  }
1568 
1569  return false;
1570 }
1571 
1572 /* returns an allocated l1-l2 with expression_equal_p
1573  l2 included in l1.
1574  */
1575 static list /* of expression */
1577 {
1578  list diff = NIL, l2bis = gen_copy_seq(l2);
1579  expression found;
1580 
1581  FOREACH(EXPRESSION, e,l1)
1582  {
1583  if (expression_eq_in_list_p(e, l2bis, &found))
1584  {
1585  gen_remove(&l2bis, found);
1586  }
1587  else
1588  {
1589  diff = CONS(EXPRESSION, e, diff);
1590  }
1591  }
1592 
1593  if (l2bis) gen_free_list(l2bis);
1594 
1595  return diff;
1596 }
1597 
1599 {
1600  syntax s = expression_syntax(e);
1601  if(syntax_call_p(s))
1602  {
1603  call c = syntax_call(s);
1605  }
1606  return false;
1607 }
1608 
1609 /* Remove some inpropriate ones...
1610 static void clean_current_availables(void)
1611 {
1612 
1613 }
1614 */
1615 
1616 static void atom_cse_expression(expression e,list * skip_list)
1617 {
1618  pips_debug(1,"considering expression:");
1619  ifdebug(1) print_expression(e);
1620  /* statement head = current_statement_head(); */
1621  syntax s = expression_syntax(e);
1622  int quality;
1623  available_scalar_pt aspt;
1624 
1625  /* only left and right side of the subscript are splittable */
1626  if(syntax_subscript_p(s)) return;
1627  if(gen_find_eq(e,*skip_list)!=gen_chunk_undefined) return;
1628  if(gen_find_eq(e,*skip_list)!=gen_chunk_undefined) return;
1629 
1630  do { /* extract every possible common subexpression */
1631  aspt = best_similar_expression(e, &quality);
1632 
1633  if (aspt) /* some common expression found. */
1634  {
1635  expression unused;
1636  if(expression_eq_in_list_p(e, *(aspt->w_effects), &unused))
1637  return;
1638  switch (syntax_tag(s))
1639  {
1640  case is_syntax_reference:
1643  return;
1644  case is_syntax_call:
1645  {
1646  call c = syntax_call(s);
1647  if (quality==MAX_SIMILARITY)
1648  {
1649  /* identical, just make a reference to the scalar,
1650  whatever the stuff stored inside.
1651  */
1652 
1655 
1656  /* Set the statement to status REAL */
1658 
1659  return;
1660  }
1661  else /* partial common expression... */
1662  {
1663  available_scalar_pt naspt;
1664  syntax sa = expression_syntax(aspt->contents);
1665  entity op = call_function(c), scalar;
1666  expression cse, cse2;
1667  statement scse;
1668  list /* of expression */ in_common, linit, lo1, lo2, old;
1669 
1670  pips_assert("AC operator",
1671  Is_Associative_Commutative(op) && op==aspt->operator);
1672  pips_assert("contents is a call", syntax_call_p(sa));
1673  call ca = syntax_call(sa);
1674 
1675  linit = call_arguments(ca);
1676 
1677  /*
1678  there is a common part to build,
1679  and a CSE to substitute in both...
1680  */
1682  *(aspt->w_effects)),
1683  aspt->available_contents);
1684 
1685  /* Case: in_common == aspt->contents
1686  * =================================
1687  */
1688  if (gen_length(linit)==gen_length(in_common))
1689  {
1690  /* just substitute lo1, don't build a new aspt. */
1691  lo1 = list_diff(call_arguments(c), in_common);
1693  call_arguments(c) =
1694  gen_nconc(lo1,
1695  CONS(EXPRESSION,
1696  entity_to_expression(aspt->scalar), NIL));
1697 
1698  /* Set the statement to status REAL */
1700  }
1701  else
1702  {
1703  lo1 = list_diff(call_arguments(c), in_common);
1704  lo2 = list_diff(linit, in_common);
1705 
1707  in_common));
1709 
1710  /* now cse is a reference to the newly created scalar. */
1711  pips_assert("a reference...",
1714  (expression_syntax(cse)));
1715  cse2 = copy_expression(cse);
1716 
1717  /* update both expressions... */
1718  old = call_arguments(c); /* in code */
1719  if (gen_length(call_arguments(c))==gen_length(in_common))
1720  {
1723  }
1724  else
1725  {
1726  call_arguments(c) = CONS(EXPRESSION, cse, lo1);
1727  }
1728  gen_free_list(old);
1729 
1730  old = call_arguments(ca);
1731  call_arguments(ca) = CONS(EXPRESSION, cse2, lo2);
1732  gen_free_list(old);
1733 
1734  set_comment_of_statement(scse, strdup("1"));
1735  insert_before_statement(scse, aspt->container, false);
1736  increase_number_of_use_by_1(scalar, aspt->container);
1737 
1738  /* don't visit it later. */
1739  gen_recurse_stop(scse);
1740 
1741  /* updates available contents */
1742  aspt->depends = CONS(ENTITY, scalar, aspt->depends);
1743  old = aspt->available_contents;
1744  aspt->available_contents = CONS(EXPRESSION, cse,
1745  list_diff(old, in_common));
1746  gen_free_list(old);
1747 
1748  /* add the new scalar as an available CSE. */
1749  naspt = make_available_scalar(scalar,
1750  aspt->container,
1753  current_available = CONS(STRING, (char*)naspt, current_available);
1754  }
1755  }
1756  break;
1757  }
1758  case is_syntax_range:
1759  default:
1760  /* nothing */
1761  return;
1762  }
1763  }
1764  } while(aspt);
1765 
1766  /* PDSon: Do not atomize:
1767  * - simple reference (ex: a, x)
1768  * - constant (ex: 2.6 , 5)
1769  * - Unary minus (ex: -a , -5)
1770  */
1771  if (!(expression_scalar_p(e)||expression_pointer_p(e)) &&
1772  !expression_constant_p(e) &&
1773  !call_unary_minus_p(e))
1774  {
1775  expression exp = NULL;
1776  /*
1777  instruction ins = statement_instruction(current_statement);
1778  if (instruction_call_p(ins))
1779  {
1780  call c_assign = instruction_call(ins);
1781 
1782  if (ENTITY_ASSIGN_P(call_function(c_assign)))
1783  {
1784  exp = EXPRESSION(CAR(CDR(call_arguments(c_assign))));
1785  }
1786  }*/
1787 
1788  if (exp != e)
1789  {
1790  statement atom;
1791 
1792  /* create a new atom... */
1794  if(atom) {
1795  /* At fisrt, this statement is set "virtual" */
1798 
1799  /* don't visit it later, just in case... */
1801  {
1802  entity scalar;
1803  call ic;
1804  syntax s = expression_syntax(e);
1806  pips_assert("it is a reference", syntax_reference_p(s));
1807  pips_assert("instruction is an assign",
1808  instruction_call_p(i)); /* ??? */
1809 
1810  scalar = reference_variable(syntax_reference(s));
1811  ic = instruction_call(i);
1812 
1813  /* if there are variants in the expression it cannot be moved,
1814  and it is not available. Otherwise I should move it?
1815  */
1816  aspt = make_available_scalar(scalar,
1818  EXPRESSION(CAR(CDR(call_arguments(ic)))));
1819 
1821  }
1822  }
1823  }
1824  else
1825  /* exp == e == <right expression of assignment>
1826  * => Atomize this expression without using temporel variable;
1827  * we use the left side variable of assignment in order to reduce
1828  * the number of the variable temporel for the comprehensive of
1829  * the code.
1830  */
1831  {
1833  if(!entity_undefined_p(scalar))
1834  {
1835  expression rhs;
1836  statement assign;
1837  syntax ref;
1838 
1841 
1843 
1846  rhs);
1847  expression_syntax(e) = ref;
1848 
1849  set_comment_of_statement(assign,strdup("1"));
1851 
1852  aspt = make_available_scalar(scalar, current_statement, rhs);
1854  }
1855  }
1856  }
1857 }
1858 
1859 static bool loop_stop(loop l,__attribute__((unused))list *skip_list)
1860 {
1862  return true;
1863 }
1864 
1865 static bool test_stop(test t,__attribute__((unused))list *skip_list)
1866 {
1869  return true;
1870 }
1871 
1872 static bool while_stop(whileloop wl,__attribute__((unused))list *skip_list)
1873 {
1875  return true;
1876 }
1877 
1878 
1879 static bool cse_atom_call_flt(call c,list *skip_list)
1880 {
1881  entity called = call_function(c);
1882 
1883  /* should avoid any W effect... */
1884  if (ENTITY_ASSIGN_P(called))
1885  {
1886  expression lhs = binary_call_lhs(c);
1887  if(get_bool_property("COMMON_SUBEXPRESSION_ELIMINATION_SKIP_LHS")) gen_recurse_stop(lhs);
1888  else if(!syntax_subscript_p(expression_syntax(lhs)))
1889  {
1890  *skip_list=CONS(EXPRESSION,lhs,*skip_list);
1891  expression var_defined =
1892  copy_expression(lhs);
1893  *w_effects = CONS(EXPRESSION, var_defined, NIL);
1894 
1895  /* Update address: w_effects always points to the end of the list of
1896  * variable modified which is filled after each statement
1897  */
1898  w_effects = &CDR(*w_effects);
1899  }
1900  }
1901  return !(io_intrinsic_p(called) || ENTITY_IMPLIEDDO_P(called));
1902 }
1903 
1904 /* side effects: use current_available and current_statement
1905  */
1906 static list /* of available_scalar_pt */
1908 {
1909  current_available = availables;
1910  current_statement = s;
1911  list skip_list = NIL;
1912 
1913  /* scan expressions in s;
1914  atomize/cse them;
1915  update availables;
1916  */
1917  gen_context_multi_recurse(s,&skip_list,
1918  /* statement_domain, current_statement_filter,
1919  current_statement_rewrite, */
1920 
1921  /* don't go inside these... */
1926 
1927  /* . */
1929 
1930  /* do the job on the found expression. */
1932  NULL);
1933  gen_free_list(skip_list);
1934 
1935  /* free_current_statement_stack(); */
1936  availables = current_available;
1937 
1940 
1941  /* Update w_effects: add the variable modified by the current statement */
1942  if (assignment_statement_p(s))
1943  {
1944  /* Update contents */
1945  expression var_defined =
1947  *w_effects = CONS(EXPRESSION, var_defined, NIL);
1948 
1949  /* Update address: w_effects always points to the end of the list of
1950  * variable modified which is filled after each statement
1951  */
1952  w_effects = &CDR(*w_effects);
1953  }
1954 
1955  return availables;
1956 }
1957 static void prune_non_constant(list effects,list * perms) {
1958  list out = NIL;
1959  FOREACH(EXPRESSION,exp,*perms) {
1961  bool conflict = false;
1962  SET_FOREACH(entity,e,re) {
1964  conflict=true;
1965  break;
1966  }
1967  }
1968  set_free(re);
1970  }
1971  gen_free_list(*perms);
1972  *perms=out;
1973 }
1974 
1975 void try_reorder_expressions(void* s,bool icm)
1976  {
1977  list gathered = NIL;
1980  else prune_singleton(&gathered);
1981  gen_context_recurse(s, gathered,
1983  gen_full_free_list(gathered);
1984  }
1985 
1986 /* top down. */
1987 static bool seq_flt(sequence s)
1988 {
1989  pips_debug(1,"considering statement:\n");
1990  ifdebug(1) {
1992  print_statement(ss);
1993  }
1994  list availables = NIL;
1995  list *top_of_w_effects;
1996 
1997  /* At first, w_effects is empty list BUT not list points to NIL!!!*/
1998  /* SG: not valid due to newgen check w_effects = &CDR(CONS(EXPRESSION, NIL, NIL));*/
1999  w_effects = &CDR(gen_cons(NIL,NIL));
2000 
2001  /* top_of_w_effects points to the top of list,
2002  * It is used to free memory later
2003  */
2004  top_of_w_effects = w_effects;
2005 
2006  /* SG we try to perform some reordering of linear expression to ease matching.
2007  * To do so we (optimistically) gather similar expressions, and when pairs are found, they are kept for further matching.
2008  * The pair gathering is store unaware, but the later process takes care of this. At worse we did some useless reordering.*/
2009  try_reorder_expressions(s,false);
2010 
2012  {
2013  availables = atomize_cse_this_statement_expressions(ss, availables);
2014  }
2015 
2016  /* Free top_of_w_effects and availables */
2017  gen_full_free_list(*top_of_w_effects);
2018  return true;
2019 }
2020 
2021 /* handle all calls not in a sequence */
2022 static bool call_flt(call c)
2023 {
2025  pips_debug(1,"considering statement:\n");
2026  ifdebug(1) { print_statement(parent); }
2027  list availables = NIL;
2028  list *top_of_w_effects = w_effects = &CDR(gen_cons(NIL,NIL));
2029  availables = atomize_cse_this_statement_expressions(parent,availables);
2030  gen_full_free_list(*top_of_w_effects);
2031  return true;
2032 }
2033 
2034 void perform_ac_cse(__attribute__((unused)) const char* name, statement s)
2035 {
2036  /* they have to be recomputed, because if ICM before. */
2037 
2038  /* set full (expr and statements) PROPER EFFECTS
2039  well, they are computed twice here...
2040  looks rather temporary.
2041  */
2042  /*
2043  full_simple_proper_effects(name, s);
2044  simple_cumulated_effects(name, s);
2045  */
2046 
2047  /* make_current_statement_stack(); */
2048  init_inserted();
2049 
2053  0);
2054 
2055  /* insert moved code in statement. */
2058  /* Remove the "inserted" mapping: */
2059  close_inserted();
2060  /*
2061  close_expr_prw_effects();
2062  close_proper_rw_effects();
2063  close_rw_effects();
2064  */
2065 }
2066 
2067 
2068 /* Pipsmake phase: Common Subexpression Elimination
2069 
2070  @param[in] module_name is the name of the module we want to apply the
2071  Common Subexpression Elimination on
2072 
2073  @return true if everything goes fine.
2074 */
2076 {
2077  bool result;
2078  const char* os = get_string_property("EOLE_OPTIMIZATION_STRATEGY");
2079 
2080  // Optimize expressions with "CSE" optimization strategy
2081  set_string_property("EOLE_OPTIMIZATION_STRATEGY", "CSE");
2083 
2084  // Restore original optimization strategy
2085  set_string_property("EOLE_OPTIMIZATION_STRATEGY", os);
2086 
2087  return result;
2088 }
2089 
2090 
2091 /* Pipsmake phase: Invariant Code Motion
2092 
2093  @param[in] module_name is the name of the module we want to apply the
2094  Invariant Code Motion on
2095 
2096  @return true if everything goes file.
2097 
2098  Beware, invariant_code_motion phase already exists too but deal with
2099  loop invariant code motion...
2100 */
2101 bool icm(const char* module_name)
2102 {
2103  bool result;
2104  const char* os = get_string_property("EOLE_OPTIMIZATION_STRATEGY");
2105 
2106  // Optimize expressions with "ICM" optimization strategy
2107  set_string_property("EOLE_OPTIMIZATION_STRATEGY", "ICM");
2109 
2110  // Restore original optimization strategy
2111  set_string_property("EOLE_OPTIMIZATION_STRATEGY", os);
2112 
2113  return result;
2114 }
2115 
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
instruction copy_instruction(instruction p)
INSTRUCTION.
Definition: ri.c:1115
call make_call(entity a1, list a2)
Definition: ri.c:269
syntax make_syntax_call(call _field_)
Definition: ri.c:2500
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
void free_extensions(extensions p)
Definition: ri.c:950
syntax copy_syntax(syntax p)
SYNTAX.
Definition: ri.c:2442
syntax make_syntax(enum syntax_utype tag, void *val)
Definition: ri.c:2491
void free_statement(statement p)
Definition: ri.c:2189
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static FILE * out
Definition: alias_check.c:128
bool entity_all_locations_p(entity e)
test if an entity is the top of the lattice
void free_arguments(cons *args)
Definition: arguments.c:218
gen_array_t gen_array_make(size_t size)
declarations...
Definition: array.c:40
void gen_array_addto(gen_array_t a, size_t i, void *what)
Definition: array.c:87
void * gen_array_item(const gen_array_t a, size_t i)
Definition: array.c:143
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
effects load_expr_prw_effects(expression)
void close_expr_prw_effects(void)
bool bound_expr_prw_effects_p(expression)
void set_cumulated_rw_effects(statement_effects)
list load_cumulated_rw_effects_list(statement)
void reset_cumulated_rw_effects(void)
void close_proper_rw_effects(void)
list proper_effects_of_expression(expression)
bool full_simple_proper_effects(const char *, statement)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_write_p(eff)
bool effects_write_variable_p(list, entity)
Definition: effects.c:1091
entity effect_entity(effect)
cproto-generated files
Definition: effects.c:52
#define effects_effects(x)
Definition: effects.h:710
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
const char * local_name(const char *s)
Does not take care of block scopes and returns a pointer.
Definition: entity_names.c:221
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
void convert_to_c_operators(void *)
Definition: optimize.c:1343
bool optimize_expressions(const char *)
pipsmake interface to apply expression optimization according to various strategy.
Definition: optimize.c:1391
void cleanup_subscripts(void *)
statement atomize_this_expression(entity(*)(entity, basic), expression)
simple_atomize.c
char * get_string_property(const char *)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
static void comment(string_buffer code, spoc_hardware_type hw, dagvtx v, int stage, int side, bool flip)
Definition: freia_spoc.c:52
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define STRING(x)
Definition: genC.h:87
#define gen_chunk_undefined
Definition: genC.h:74
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void gen_full_free_list(list l)
Definition: genClib.c:1023
void * malloc(YYSIZE_T)
void free(void *)
bool entities_may_conflict_p(entity e1, entity e2)
Check if two entities may conflict.
Definition: conflicts.c:984
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
void gen_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
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
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
bool gen_false(__attribute__((unused)) gen_chunk *unused)
Return false and ignore the argument.
Definition: genClib.c:2796
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
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 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_once(const void *vo, list l)
Prepend an item to a list only if it is not already in the list.
Definition: list.c:722
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
list gen_cons(const void *item, const list next)
Definition: list.c:888
#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
void * gen_find_eq(const void *item, const list seq)
Definition: list.c:422
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#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
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
bool statement_loop_p(statement)
Definition: statement.c:349
statement make_assign_statement(expression, expression)
Definition: statement.c:583
statement update_statement_instruction(statement, instruction)
Replace the instruction in statement s by instruction i.
Definition: statement.c:3039
bool assignment_statement_p(statement)
Test if a statement is an assignment.
Definition: statement.c:135
bool empty_comments_p(const char *)
Definition: statement.c:107
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define DEFINE_LOCAL_STACK(name, type)
#define same_string_p(s1, s2)
#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
#define stack_undefined
Definition: newgen_stack.h:55
#define string_undefined
Definition: newgen_types.h:40
#define string_undefined_p(s)
Definition: newgen_types.h:41
struct cons * list
Definition: newgen_types.h:106
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
struct _newgen_struct_atom_ * atom
void normalize_all_expressions_of(void *obj)
Definition: normalize.c:668
void unnormalize_expression(void *st)
void unnormalize_expression(expression exp): puts all the normalized field of expressions in "st" to ...
Definition: normalize.c:452
void print_syntax(syntax s)
Definition: expression.c:121
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
string expression_to_string(expression e)
Definition: expression.c:77
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
void set_string_property(const char *, const char *)
#define make_expression_list(stats...)
#define IO_CALL_P(call)
#define MAX_OPERATOR_NAME
#define binary_call_rhs(c)
#define ENTITY_ASSIGN_P(e)
#define MINUS_OPERATOR_NAME
#define ENTITY_UNARY_MINUS_P(e)
#define ENTITY_IMPLIEDDO_P(e)
#define PLUS_OPERATOR_NAME
#define NORMALIZE_EXPRESSION(e)
#define statement_block_p(stat)
#define expression_scalar_p(e)
#define binary_call_lhs(c)
#define EOLE_PROD_OPERATOR_NAME
#define EOLE_SUM_OPERATOR_NAME
#define instruction_block(i)
#define MINUS_C_OPERATOR_NAME
#define MULTIPLY_OPERATOR_NAME
#define entity_constant_p(e)
#define PLUS_C_OPERATOR_NAME
#define MIN_OPERATOR_NAME
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
bool io_intrinsic_p(entity e)
rue is a statement s is an io intrinsic
Definition: entity.c:1655
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
bool commutative_call_p(call c)
Test if we are allowed to commute operations.
Definition: entity.c:2661
entity entity_empty_label(void)
Definition: entity.c:1105
bool entity_empty_label_p(entity e)
Definition: entity.c:666
set get_referenced_entities(void *elem)
retrieves the set of entities used in elem beware that this entities may be formal parameters,...
Definition: entity.c:3063
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression Pvecteur_to_expression(Pvecteur vect)
AP, sep 25th 95 : some usefull functions moved from static_controlize/utils.c.
Definition: expression.c:1825
bool expression_call_p(expression e)
Definition: expression.c:415
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
call expression_call(expression e)
Definition: expression.c:445
void update_expression_syntax(expression e, syntax s)
frees expression syntax of e and replace it by the new syntax s
Definition: expression.c:3564
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 expression_pointer_p(expression e)
we get the type of the expression by calling expression_to_type() which allocates a new one.
Definition: expression.c:506
expression make_op_exp(char *op_name, expression exp1, expression exp2)
================================================================
Definition: expression.c:2012
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
bool same_expression_p(expression e1, expression e2)
this is slightly different from expression_equal_p, as it will return true for a+b vs b+a
Definition: expression.c:1426
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
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
entity make_new_scalar_variable(entity, basic)
Definition: variable.c:741
#define loop_body(x)
Definition: ri.h:1644
#define test_domain
newgen_entity_domain_defined
Definition: ri.h:418
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference_p(x)
Definition: ri.h:2728
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define normalized_linear_p(x)
Definition: ri.h:1779
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define range_upper(x)
Definition: ri.h:2290
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define syntax_call_p(x)
Definition: ri.h:2734
#define instruction_loop(x)
Definition: ri.h:1520
#define syntax_cast(x)
Definition: ri.h:2739
#define test_false(x)
Definition: ri.h:2837
#define basic_pointer_p(x)
Definition: ri.h:635
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_cast
Definition: ri.h:2694
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
@ is_syntax_subscript
Definition: ri.h:2696
#define range_increment(x)
Definition: ri.h:2292
#define instruction_domain
newgen_functional_domain_defined
Definition: ri.h:202
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define cast_expression(x)
Definition: ri.h:747
#define statement_label(x)
Definition: ri.h:2450
#define entity_undefined_p(x)
Definition: ri.h:2762
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define expression_normalized(x)
Definition: ri.h:1249
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define reference_indices(x)
Definition: ri.h:2328
#define statement_extensions(x)
Definition: ri.h:2464
#define instruction_sequence(x)
Definition: ri.h:1514
#define syntax_call(x)
Definition: ri.h:2736
#define instruction_call_p(x)
Definition: ri.h:1527
#define expression_undefined_p(x)
Definition: ri.h:1224
#define test_condition(x)
Definition: ri.h:2833
#define range_lower(x)
Definition: ri.h:2288
#define whileloop_body(x)
Definition: ri.h:3162
#define whileloop_domain
newgen_variable_domain_defined
Definition: ri.h:466
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define instruction_call(x)
Definition: ri.h:1529
#define loop_range(x)
Definition: ri.h:1642
#define call_arguments(x)
Definition: ri.h:711
#define syntax_cast_p(x)
Definition: ri.h:2737
#define whileloop_condition(x)
Definition: ri.h:3160
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define syntax_subscript_p(x)
Definition: ri.h:2743
#define level
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
static bool cse_call_flt(call c, __attribute__((unused)) list *inserted)
Avoid visit the left side of assign statement.
static void add_ref_ent(reference r)
static bool moveable_to(list le, statement s)
Whether sg with effects le can be moved up to s.
static void insert_rwt(statement s)
Insert the new statements created.
static available_scalar_pt best_similar_expression(expression e, int *best_quality)
static list insertion_statement_in_correct_position(statement news, list l)
Insert statement s in the list of statement l.
static void push_nesting(statement s)
Keep track of statement nesting.
static void atomize_or_associate(expression e)
static void do_gather_all_expressions_perms(list sterns, list *perms)
static void remove_statement_redundant(statement s, list *inserted)
Remove statement redundant inserted before statement s.
static bool do_gather_all_expressions(expression e, list *gathered)
static list nesting
assumes:
static bool while_stop(whileloop wl, __attribute__((unused)) list *skip_list)
static bool call_unary_minus_p(expression e)
static list * w_effects
PDSon: w_effect store all the variables modified in the sequence of statement.
static int current_level(void)
The nesting depth of the current statement.
static bool cse_atom_call_flt(call c, list *skip_list)
static void set_comment_of_statement(statement s, char *new_comment)
Update the field 'comments' of a statement.
static list seen
static bool atomizable_sub_expression_p(expression e)
Atomizable if some computation.
static void atomize_whileloop(whileloop w)
bool icm(const char *module_name)
Pipsmake phase: Invariant Code Motion.
static void do_atomize_if_different_level(expression e, int level)
Atomize sub expressions with.
static bool expression_eq_in_list_p(expression e, list l, expression *f)
Define forward.
static void prune_singleton(list *l)
static expression expr_left_side_of_assign_statement(statement stat)
Return the expression in the left side of an assign statement.
static bool call_flt(call c)
handle all calls not in a sequence
static void atomize_instruction(instruction i)
Atomize an instruction with call.
static void atom_cse_expression(expression e, list *skip_list)
Remove some inpropriate ones...
static bool prepare_icm(statement s)
static bool test_stop(test t, __attribute__((unused)) list *skip_list)
static bool loop_stop(loop l, __attribute__((unused)) list *skip_list)
static bool entity_as_arguments(entity ent, statement stat)
Verify if entity ent is an argument in the right expression of the assign statement stat.
static void atomize_call(call c, int level)
static list common_expressions(list args, list avails)
of expression
static bool expr_cse_flt(expression e, __attribute__((unused)) list *skip_list)
whether to get in here, whether to atomize...
static void prune_non_constant(list effects, list *perms)
static void loop_rwt(loop l)
static statement update_number_of_use(entity ent, list lst_stat, int up_down)
Update the number of use of statement defining 'ent' which is a member of list lst_stat with step up_...
static bool interference_on(entity var, list les)
Compute if an effect list Some effect in les interfere with var.
static void insert_before_statement(statement news, statement s, bool last)
Just for test static void dump_list_of_statement(list l) { fprintf(stderr, "\n===== Dump List: \n"); ...
static list current_available
statement stack to current statement.
static bool seq_flt(sequence s)
top down.
static void increase_number_of_use_by_1(entity ent, statement container)
Increase number of use of variable ent by one.
static bool loop_flt(loop l)
static expression right_side_of_assign_statement(statement stat)
bool common_subexpression_elimination(const char *module_name)
Pipsmake phase: Common Subexpression Elimination.
static void atomize_test(test t)
static void reorder_pointer_expression(expression e)
make sure expressions are ordered with pointer first
#define MAX_SIMILARITY
static void add_call_ent(call c)
static list list_diff(list l1, list l2)
of expression
static char * table_of_AC_operators[]
option:
static bool number_of_use_greater_1(statement s)
PDSon: I use the field 'comments' of statement for counting its number of use.
void try_reorder_expressions(void *s, bool icm)
static int similarity(expression e, available_scalar_pt aspt)
Find the commun sub-expression between e & aspt.
static bool side_effects_p(expression e)
There is a side effect if there is a W effect in the expression.
static list get_all_entities(expression e)
static bool Is_Associative_Commutative(entity e)
static gen_array_t group_expr_by_level(int nlevels, list le)
of list of expressions
static void pop_nesting(statement s)
Pop the current statement from nesting list.
static bool cse_expression_flt(expression e, list *inserted)
static int expr_level_of(expression e)
The level can be queried for a sub expression.
static void atomize_or_associate_for_level(expression e, int level)
static int level_of(list le)
Return the level of this expression, using the current nesting list.
static statement statement_of_level(int level)
or for a statement.
static bool currently_nested_p(void)
Test if the current statement is not the top one:
void perform_ac_cse(__attribute__((unused)) const char *name, statement s)
static statement current_statement
static bool try_reorder_expression_call(expression e, list availables)
static entity left_side_of_assign_statement(statement stat)
Return the entity in left side of an assign statement.
static available_scalar_pt make_available_scalar(entity scalar, statement container, expression contents)
static bool icm_atom_call_flt(call c)
Don't go into I/O calls...
static expression find_equal_expression_not_in_list(expression e, list avails, list seen)
static bool expression_in_list_p(expression e, list seen)
static list atomize_cse_this_statement_expressions(statement s, list availables)
side effects: use current_available and current_statement
#define NO_SIMILARITY
struct available_scalar_t * available_scalar_pt
void perform_icm_association(const char *name, statement s)
Perform ICM and association on operators.
#define ifdebug(n)
Definition: sg.c:47
GENERIC_LOCAL_FUNCTION(directives, step_directives)
Copyright 2007, 2008, 2009 Alain Muller, Frederique Silber-Chaussumier.
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
performs Associative-Commutative Common Subexpression Elimination on sequences.
list depends
NULL for references.
list * w_effects
part of which is available
expression contents
statement in which it appears (for atomization)
entity operator
the entity which holds the value? or partial?
statement container
W effects on these invalidates the scalar.
list available_contents
call or reference...
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:4047
bool clone(const string)
char * int2a(int)
util.c
Definition: util.c:42
A gen_chunk is used to store every object.
Definition: genC.h:58
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_val(v)
#define vecteur_var(v)
#define vecteur_succ(v)
#define VECTEUR_NUL_P(v)
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
Pvecteur vect_add(Pvecteur v1, Pvecteur v2)
package vecteur - operations binaires
Definition: binaires.c:53
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2)
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2): allocation d'un vecteur v dont la valeur est la di...
Definition: binaires.c:75