PIPS
simdizer.c
Go to the documentation of this file.
1 /*
2 
3  $Id: simdizer.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 #include "genC.h"
29 #include "linear.h"
30 #include "ri.h"
31 #include "effects.h"
32 
33 #include "resources.h"
34 
35 #include "misc.h"
36 #include "ri-util.h"
37 #include "prettyprint.h"
38 #include "effects-util.h"
39 #include "text-util.h"
40 #include "pipsdbm.h"
41 
42 #include "effects-generic.h"
43 #include "effects-convex.h"
44 #include "effects-simple.h"
45 #include "accel-util.h"
46 
47 #include "ray_dte.h"
48 #include "sommet.h"
49 #include "sg.h"
50 #include "polyedre.h"
51 
52 #include "sac.h"
53 #include "ricedg.h"
54 #include "control.h"
55 #include "callgraph.h"
56 
57 #include "effects-convex.h"
58 
59 
60 static hash_table matches = NULL;
61 
62 /*
63  * This function stores in the matches hash table the
64  * simd pattern matches for each statement
65  */
67 {
69  FOREACH(STATEMENT, s,l)
70  {
72 
73  if (match != NIL)
74  hash_put(matches, (void *)s, (void *)match);
75  }
76 }
77 
78 /*
79  This function frees the matches hash table
80  */
82 {
84 }
85 
86 /*
87  This function gets the simd pattern matches
88  for the statement s
89  */
91 {
93  return m;
94 }
95 
96 /*
97  This function gets the simd pattern matches
98  for the statement s checking that the opcodeClass
99  of the match is kind
100  */
102 {
104 
105  for( ; l!=NIL; l=CDR(l))
106  {
107  match m = MATCH(CAR(l));
108  if (match_type(m) == kind)
109  return m;
110  }
111 
112  return match_undefined;
113 }
114 
115 /*
116  * This function gets the simd pattern matches opcodeClass's
117  * list for the statement s
118  */
120 {
122 
125 
126  return out;
127 }
128 
130 
131 /* this code is here because levels information seems inaccurate
132  * so it checks all the possible conflict between @p source and  @p sink
133  * that could have generated @p c
134  * and then instead of using references_may_conflict, it assumes we are in ssa form
135  * which should be ok thanks to scalar renaming,
136  * and symbolically computes the distance between each reference
137  */
138 static bool conflict_is_a_real_conflict_p(conflict c, statement source, statement sink, size_t loop_level) {
139  pips_assert("true", source==source && sink==sink);
140  cone co = conflict_cone(c);
141  if(!cone_undefined_p(co)) {
142  bool no_intra_loop_dep = true;
143  FOREACH(INT,i,cone_levels(co))
144  if(i == (int) loop_level +1 )
145  no_intra_loop_dep = false;
146 #if 0 /* hack no longer needed , simple is beautiful */
147  if(!no_intra_loop_dep) /* there seems to be an intra loop dep, verify this */ {
149  source_ref = effect_any_reference(conflict_source(c));
150  if(same_entity_p(reference_variable(sink_ref),reference_variable(source_ref))) {
151  list sink_effects = load_proper_rw_effects_list(sink),
152  source_effects = load_proper_rw_effects_list(source);
153  sink_effects = effect_read_p(conflict_sink(c))?
154  effects_read_effects(sink_effects):
155  effects_write_effects(sink_effects);
156  source_effects = effect_read_p(conflict_source(c))?
157  effects_read_effects(source_effects):
158  effects_write_effects(source_effects);
159  set sink_refs = set_make(set_pointer),
160  source_refs = set_make(set_pointer);
161 
162  FOREACH(EFFECT,eff,sink_effects)
164  set_add_element(sink_refs,sink_refs,effect_any_reference(eff));
165  FOREACH(EFFECT,eff,source_effects)
167  set_add_element(source_refs,source_refs,effect_any_reference(eff));
168  no_intra_loop_dep = true;
169  SET_FOREACH(reference,rsink,sink_refs) {
170  expression esink = reference_to_expression(rsink);
171  SET_FOREACH(reference,rsource,source_refs) {
172  expression esource = reference_to_expression(rsource);
173  expression d = distance_between_expression(esink,esource);
174  intptr_t val;
175  if(expression_undefined_p(d) ||
176  !expression_integer_value(d,&val) ||
177  val == 0) {
178  no_intra_loop_dep = false;
179  }
180  }
181  }
182  set_free(sink_refs);
183  set_free(source_refs);
184  gen_free_list(sink_effects);
185  gen_free_list(source_effects);
186  }
187  }
188 #endif
189  return !no_intra_loop_dep;
190  }
191  else
192  return true;
193 }
194 
195 static bool successor_only_has_rr_conflict_p(vertex v,successor su, size_t loop_level)
196 {
197  bool all_rr = true;
199  {
202  )
203  {
204  pips_debug(3,
205  "conflict skipped between %s and %s\n",
208  }
209  else {
210 #if 0
212  if(ENDP(inter)) // why is this conflict generated ?!?
213  {
214  pips_debug(3,
215  "conflict skipped between %s and %s\n",
218  continue;
219  }
220  gen_full_free_list(inter);
221 #endif
222  /* regions tell us there is a conflict.
223  * check if the dependence is loop carried or not
224  * */
226 
227  if(!all_rr) {
228  pips_debug(3,"conflict found :\n");
229  ifdebug(3) {
232  }
233  }
234  else {
235  pips_debug(3,
236  "conflict not relevant between:\n");
237  ifdebug(3) {
240  }
241  }
242  }
243  }
244  return all_rr;
245 }
246 
247 /*
248  * This function frees the successors list
249  */
251 {
253  hash_table_free(equivalence_table);/* leak spotted !*/
255 }
256 
258 {
260  pips_assert("table is correct",equivalences!= HASH_UNDEFINED_VALUE);
261 
264 
265  set stail = set_make(set_pointer);
266  set_assign_list(stail,tail);
267 
268  set_intersection(eq,eq,stail);
269  set_free(stail);
270  ifdebug(3) {
271  pips_debug(3,"non conficting statement with\n");
272  print_statement(s);
274  print_statement(st);
275  }
276 
277  return eq;
278 }
280 {
281  pips_assert("true", s==s);
283  SET_FOREACH(statement,st,stats)
284  {
286  set tmp = set_make(set_pointer);
287  set_intersection(tmp,*matches,smt);
288  if(set_empty_p(tmp))
289  {
290  set_free(tmp);
291  }
292  else {
294  if( simd_check_argType()){
295  *matches=tmp;
296  set_add_element(out,out,st);
297  }
298  else {
299  ifdebug(3){
300  pips_debug(3,"following statement does not have good arg type\n");
301  print_statement(st);
302  }
303  }
304  }
305  set_free(smt);
306  }
307  return out;
308 }
309 
311 {
313  {
314  *l=CONS(EXPRESSION,e,*l);
315  return false;
316  }
317  return true;
318 }
319 
321 {
322  list out = NIL;
324  return out;
325 }
326 
327 #if 0
328 static void sac_sort_expressions_reductions_last(list *l)
329 {
330  list tail = NIL;
331  list head = NIL;
334  tail=CONS(EXPRESSION,exp,tail);
335  else
336  head=CONS(EXPRESSION,exp,head);
337  tail=gen_nreverse(tail);
338  head=gen_nreverse(head);
339  gen_free_list(*l);
340  *l=gen_nconc(head,tail);
341 }
342 #endif
343 
345 {
348  list iter=exp1;
349  FOREACH(EXPRESSION,e0,exp0)
350  {
351  expression e1 = EXPRESSION(CAR(iter));
352  expression distance = distance_between_expression(e1,e0);
353  intptr_t val=0;
354  if(!expression_undefined_p(distance))
355  {
356  (void)expression_integer_value(distance,&val);
357  free_expression(distance);
358  if(val) return true;
359  }
360  POP(iter);
361  if(ENDP(iter)) break;
362  }
363  return false;
364 }
365 static int compare_statements_on_ordering(const void * v0, const void * v1)
366 {
367  const statement s0 = *(const statement*)v0;
368  const statement s1 = *(const statement*)v1;
369  if (statement_ordering(s0) > statement_ordering(s1)) return 1;
370  if (statement_ordering(s0) < statement_ordering(s1)) return -1;
371  return 0;
372 }
373 
374 #if 0
375 static int compare_statements_on_distance(const void * v0, const void * v1)
376 {
377  const statement s0 = *(const statement*)v0;
378  const statement s1 = *(const statement*)v1;
381  /* hook for reductions :
382  * it is less painful to load reduction in a bad order than other reference,
383  * so we reorder the expressions exp0 in order to check reductions last
384  */
385  sac_sort_expressions_reductions_last(&exp0);
386  sac_sort_expressions_reductions_last(&exp1);
387  list iter=exp1;
388  int res = 0;
389  FOREACH(EXPRESSION,e0,exp0)
390  {
391  if (ENDP(iter)) {
392  break;
393  }
394  expression e1 = EXPRESSION(CAR(iter));
395  expression distance = distance_between_expression(e1,e0);
396  intptr_t val=0;
397  if(!expression_undefined_p(distance))
398  {
399  (void)expression_integer_value(distance,&val);
400  free_expression(distance);
401  if((res=val)) break;
402  }
403  POP(iter);
404  }
405  gen_free_list(exp0);
406  gen_free_list(exp1);
407  return res?res:compare_statements_on_ordering(v0,v1);
408 }
409 #endif
410 
411 static statement origin=NULL;
413 static void reset_statement_origin() {origin=NULL;}
414 
415 static int compare_statements_on_distance_to_origin(const void* ps0, const void* ps1) {
416 
417  const statement s0 = *(const statement*)ps0;
418  const statement s1 = *(const statement*)ps1;
422  size_t dist0=0,
423  dist1=0;
424  static const int dinf=1000;
425 
426  list iter0 = exp0,iter1=exp1;
427  FOREACH(EXPRESSION,eo,expo)
428  {
429  expression e0 = ENDP(iter0)? expression_undefined:EXPRESSION(CAR(iter0)),
430  e1 = ENDP(iter1)? expression_undefined:EXPRESSION(CAR(iter1));
433  intptr_t val0=0, val1;
434  if(!expression_undefined_p(distance0))
435  {
436  if(expression_integer_value(distance0,&val0)) {
437  dist0+=val0*val0;
438  }
439  else dist0+=dinf*dinf;
440  free_expression(distance0);
441 
442  }
443  else if(expression_scalar_p(e0) && expression_scalar_p(e1))
444  dist0+=1;
445  else
446  dist0+=dinf*dinf;
447  if(!expression_undefined_p(distance1))
448  {
449  if(expression_integer_value(distance1,&val1)) {
450  dist1+=val1*val1;
451  }
452  else dist1+=dinf*dinf;
453  free_expression(distance1);
454 
455  }
456  else if(expression_scalar_p(e0) && expression_scalar_p(e1))
457  dist1+=1;
458  else
459  dist1+=dinf*dinf;
460  POP(iter0);
461  POP(iter1);
462  }
463  gen_free_list(expo);
464  gen_free_list(exp0);
465  gen_free_list(exp1);
466  return dist0>dist1? 1 : dist0 == dist1 ? 0 : -1;
467 }
468 
469 static int compare_list_from_length(const void *v0, const void *v1)
470 {
471  const list l0=*(const list*)v0;
472  const list l1=*(const list*)v1;
473  size_t n0 = gen_length(l0);
474  size_t n1 = gen_length(l1);
475  return n0==n1 ? 0 : n0 > n1 ? 1 : -1;
476 }
477 
479 {
481  list heads = NIL;
482  while(!ENDP(ordered)) {
483  statement head = STATEMENT(CAR(ordered));
484  list firsts = CONS(STATEMENT,head,NIL);
485  list lasts = NIL;
486  FOREACH(STATEMENT,st,CDR(ordered))
487  {
489  firsts=CONS(STATEMENT,st,firsts);
490  else
491  lasts=CONS(STATEMENT,st,lasts);
492  }
493  gen_free_list(ordered);
494  set_statement_origin(head);
498  heads=CONS(LIST,firsts,heads);
499  ordered=lasts;
500  }
502  list out = NIL;
503  FOREACH(LIST,l,heads)
504  out=gen_nconc(l,out);
505  gen_free_list(heads);
506  return out;
507 }
510  return order_isomorphic_statements_list(ordered);
511 }
512 
513 /*
514  * This function stores in the hash_table equivalence_table
515  * all statement equivalent to those in l
516  *
517  * it is done by iterating over the `dependence_graph'
518  */
520 {
523 
524  /* for faster access */
525  set statements = set_make(set_pointer);
526  set_assign_list(statements,*l);
528 
529  /* first extract corresponding vertices */
531  {
532  statement s = vertex_to_statement(a_vertex);
533  if(set_belong_p(statements,s))
534  hash_put(counters,a_vertex,(void*)0);
535  }
536  /* then count the references between each other */
537  for(void *k,*v,*iter=NULL; (iter=hash_table_scan(counters,iter,&k,&v));)
538  {
540  {
541  /* do not take into account backward references, or R-R conflicts */
543  !successor_only_has_rr_conflict_p((vertex)k,su,loop_level) )
544  {
545  void* counter = hash_get(counters,successor_vertex(su));
546  if(counter != HASH_UNDEFINED_VALUE)
547  {
548  intptr_t value = (intptr_t)counter;
549  ++value;
550  pips_debug(4,"counter now is %td for\n",value);
552  pips_debug(4,"referenced by\n");
554  hash_update(counters,successor_vertex(su),(void*)value);
555  }
556  }
557  }
558  }
559 
560  /* now recursievly retreive the head of each vertex with no reference on them
561  * and reorder initial statement list */
562  list new_l = NIL;
563  while(!hash_table_empty_p(counters))
564  {
565  set head = set_make(set_pointer);
566  /* fill the head */
567  HASH_MAP(k,v,if((intptr_t)v == 0) set_add_element(head,head,k), counters);
568  /* found nothing, assume we are in the tail */
569  if(set_empty_p(head))
570  {
571  list equivalence_list = NIL;
572  HASH_MAP(k,v,equivalence_list=CONS(STATEMENT,vertex_to_statement((vertex)k),equivalence_list),counters);
573  HASH_MAP(k,v, hash_put(equivalence_table,vertex_to_statement((vertex)k),equivalence_list), counters);
574  hash_table_clear(counters);
575  new_l = gen_nconc(new_l, equivalence_list);
576  }
577  /* remove those vertex from the head and decrease references elsewhere */
578  else
579  {
580  list equivalence_list = NIL;
581  { SET_FOREACH(vertex,v,head) equivalence_list=CONS(STATEMENT,vertex_to_statement(v),equivalence_list); }
583 
584  SET_FOREACH(vertex,v,head) {
586  void* counter = hash_get(counters,successor_vertex(su));
587  /* do not take into account backward references and ignored statements */
589  {
590  intptr_t value = (intptr_t)counter;
591  --value;
592  pips_assert("not missed something",value>=0);
593  hash_update(counters,successor_vertex(su),(void*)value);
594  }
595  }
597  pips_internal_error("failed");
599  hash_del(counters,v);
600  }
601  new_l = gen_nconc(new_l, equivalence_list);
602 
603  }
604  set_free(head);
605  }
606  hash_table_free(counters);
607  gen_free_list(*l);
608  *l = new_l;
609 }
610 
611 static list simdize_simple_statements_pass2(list seq, float * simdCost)
612 {
613  list newseq=NIL;
614 
615  //argument info dependencies are local to each sequence -> RESET
617 
618  set visited = set_make(set_pointer);
619 
620  /* Traverse to list to group isomorphic statements */
621  for(list i = seq;!ENDP(i);POP(i))
622  {
623  statement si = STATEMENT(CAR(i));
624  if(!set_belong_p(visited,si))
625  {
626  set_add_element(visited,visited,si);
627  ifdebug(3){
628  pips_debug(3,"trying to match statement\n");
629  print_statement(si);
630  }
631 
632  /* if this is not a recognized statement (ie, no match), skip it */
633  set group_matches = get_statement_matching_types(si);
634  if (set_empty_p(group_matches) )
635  {
636  pips_debug(3,"no match found\n");
638  newseq = CONS(STATEMENT,si,newseq);
639  continue;
640  }
641  else
642  {
643  ifdebug(3) {
644  pips_debug(3,"matching opcode found:\n");
645  SET_FOREACH(opcodeClass,oc,group_matches)
646  pips_debug(3,"%s\n",opcodeClass_name(oc));
647  }
648  }
649 
651  ifdebug(3) {
652  pips_debug(3,"examining following statments:\n");
653  print_statements(CDR(i));
654  }
655 
656  /* try to find all the compatible isomorphic statements after the
657  * current statement
658  */
659  /* if the matches for statement sj and for the group have a non-empty
660  * intersection, and the move is legal (ie, does not break dependency
661  * chain) then we can add the statement sj to the group.
662  */
663  set non_conflicting = extract_non_conflicting_statements(si,CDR(i));
664  /* filter out already visited statements */
665  set_difference(non_conflicting,non_conflicting,visited);
666  set isomorphics = extract_matching_statements(si,non_conflicting,&group_matches);
667  if(set_empty_p(isomorphics))
668  {
669  ifdebug(3){
670  pips_debug(3,"following statement cannot be moved\n");
671  print_statement(si);
672  }
674  newseq = CONS(STATEMENT,si,newseq);
675  }
676  else
677  {
678  set_add_element(isomorphics,isomorphics,si);
679  ifdebug(3){
680  pips_debug(3,"following statements matches!\n");
681  SET_FOREACH(statement,sj,isomorphics)
682  print_statement(sj);
683  }
684  list iso_stats = order_isomorphic_statements(isomorphics);
685  set_free(isomorphics);
686  for(list iso_iter=iso_stats;!ENDP(iso_iter);)
687  {
688  simdstatement ss = make_simd_statements(group_matches, iso_iter);
690  {
692  newseq = CONS(STATEMENT,si,newseq);
693  POP(iso_iter);
694  break;
695  }
696  else
697  {
698  newseq=gen_append(generate_simd_code(ss,simdCost),newseq);
699  for(intptr_t i= opcode_vectorSize(simdstatement_opcode(ss));i!=0;i--)
700  {
701  set_add_element(visited,visited,STATEMENT(CAR(iso_iter)));
702  POP(iso_iter);
703  }
704  iso_iter=order_isomorphic_statements_list(iso_iter);
705  }
706  }
707  set_free(group_matches);
708  //gen_free_list(iso_stats);
709  }
711  }
712  }
714  newseq=gen_nreverse(newseq);
715 
716  /* Free the list of statements info */
717 
718  /* Set the new list as the statements' instructions */
719  return newseq;
720 }
721 
724 
725 typedef struct {
728  bool result; /* whether simdizer() did something useful */
730 
731 /*
732  * This function tries to simdize with two algorithms.
733  *
734  * `simdize_simple_statements_pass1' attempts to simdize by grouping
735  * the statements that have the same simd number.
736  *
737  * `simdize_simple_statements_pass2' attempts to simdize by grouping
738  * as many statements as possible together.
739  */
741 {
742  /* not much we can do with a single statement, or with
743  * "complex" statements (ie, with tests/loops/...)
744  */
745  if (statement_block_p(s))
746  {
747  graph dependence_graph = sc->dg;
749  /* we cannot handle anything but sequence of calls */
750  list iter = statement_block(s);
753 
754  list new_seq = NIL;
755  while(!ENDP(iter))
756  {
757  list seq = NIL;
758  for(;!ENDP(iter);POP(iter))
759  {
760  statement st = STATEMENT(CAR(iter));
763  else {
764  if(statement_call_p(st))
765  seq=CONS(STATEMENT,st,seq);
766 
767  if(!statement_call_p(st)||ENDP(CDR(iter)))
768  {
769  /* process already existing statements */
770  if(!ENDP(seq))
771  {
772  seq=gen_nreverse(seq);
773 
776 
777  float saveSimdCost = 0;
778  list simdseq = simdize_simple_statements_pass2(seq, &saveSimdCost);
779 
780  pips_debug(2,"opcode cost1 %f\n", saveSimdCost);
781 
782  if((saveSimdCost >= 0.0))
783  {
784  new_seq=gen_append(new_seq,seq);
785  gen_free_list(simdseq);
786  }
787  else
788  {
789  new_seq=gen_append(new_seq,simdseq);
790  gen_free_list(seq);
791  sc->result |= true;
792  }
793 
796  seq=NIL;
797 
798  }
799  if(!statement_call_p(st))
800  new_seq=gen_append(new_seq,CONS(STATEMENT,st,NIL));
801  }
802  }
803 
804  }
805  }
807  gen_append(statement_block(s),new_seq);
808  }
809 }
810 
811 
812 /*
813  * simple filter for `simdizer'
814  * Do not recurse through simple calls, for better performance
815  */
817 {
818  return ! ( instruction_call_p( statement_instruction(s) ) ) ;
819 }
820 
822 {
823  if(sac_aligned_entity_p(e))
824  {
825  return strdup("SAC generated temporary array");
826  }
827  else if(simd_vector_entity_p(e))
828  {
829  string s,g = basic_to_string(entity_basic(e));
830  asprintf(&s,"PIPS:SAC generated %s vector(s)", g);
831  free(g);
832  return s;
833  }
834  else
835  return strdup("PIPS:SAC generated variable");
836 }
837 
838 static bool incr_counter(loop l, simdizer_context *sc) {
839  pips_assert("true", l==l);
840  sc->nb_enclosing_loops++;
841  return true;
842 }
843 static void decr_counter(loop l, simdizer_context *sc) {
844  pips_assert("true", l==l);
845  sc->nb_enclosing_loops--;
846 }
847 
848 
849 
850 /*
851  * main entry function
852  * basically run `simdize_simple_statements' on all sequences
853  */
854 bool simdizer(char * mod_name)
855 {
856  /* get the resources */
857  statement mod_stmt = (statement)
858  db_get_memory_resource(DBR_CODE, mod_name, true);
859 
860  set_current_module_statement(mod_stmt);
862  set_ordering_to_statement(mod_stmt);
863  simdizer_context sc = { .dg = (graph) db_get_memory_resource(DBR_DG, mod_name, true),
864  .nb_enclosing_loops = 0,
865  .result = false };
866  set_simd_treematch((matchTree)db_get_memory_resource(DBR_SIMD_TREEMATCH,"",true));
867  set_simd_operator_mappings(db_get_memory_resource(DBR_SIMD_OPERATOR_MAPPINGS,"",true));
868  statement_effects se = (statement_effects)db_get_memory_resource(DBR_PROPER_EFFECTS,mod_name,true);
869  remove_preferences(se);
873 
874  debug_on("SIMDIZER_DEBUG_LEVEL");
875 
876  /* Now do the job */
880  NULL);
881 
882  pips_assert("Statement is consistent after SIMDIZER",
883  statement_consistent_p(mod_stmt));
884 
885  /* Reorder the module, because new statements have been added */
886  clean_up_sequences(mod_stmt);
887  module_reorder(mod_stmt);
888  DB_PUT_MEMORY_RESOURCE(DBR_CODE, mod_name, mod_stmt);
889  DB_PUT_MEMORY_RESOURCE(DBR_CALLEES, mod_name, compute_callees(mod_stmt));
890  //DB_PUT_MEMORY_RESOURCE(DBR_DG, mod_name, dependence_graph);
891 
892  /* update/release resources */
900 
901  debug_off();
902 
903  return sc.result;
904 }
905 
906 
907 static void do_simdizer_init(call c)
908 {
909 #define SWAP_ARGUMENTS(c) do { call_arguments(c)=gen_nreverse(call_arguments(c)) ; return ;} while(0)
910 #define NOSWAP_ARGUMENTS(c) return
911  if(commutative_call_p(c))
912  {
913  pips_assert("commutative call are binary calls",gen_length(call_arguments(c))==2);
914  expression e0 = binary_call_lhs(c),
915  e1 = binary_call_rhs(c);
916  /* constant first */
919  /* then scalar */
922 
923  /* we finally end with two references */
925  {
926  expression distance = distance_between_expression(e0,e1);
927  intptr_t val;
928  if( !expression_undefined_p(distance) && expression_integer_value(distance,&val))
929  {
930  free_expression(distance);
931  if(val <= 0) NOSWAP_ARGUMENTS(c);
932  else SWAP_ARGUMENTS(c) ;
933  }
934  else
935  {
936  entity ent0 = expression_to_entity(e0);
937  entity ent1 = expression_to_entity(e1);
938  if(compare_entities(&ent0,&ent1)<=0) NOSWAP_ARGUMENTS(c);
939  else SWAP_ARGUMENTS(c) ;
940  }
941  }
942  else
943  {
944  string msg = words_to_string(Words_Call(c,0,true,true));
945  pips_user_warning("unable to decide how to commute %s\n",msg);
946  free(msg);
947  }
948  }
949 #undef SWAP_ARGUMENTS
950 #undef NOSWAP_ARGUMENTS
951 }
952 
954  if(statement_block_p(s)) {
955  list blocks = NIL;
956  list iter=statement_block(s);
957  while(!ENDP(iter)) {
958  list curr = NIL;
959  bool block_created = false;
960  do {
961  statement st = STATEMENT(CAR(iter));
962  POP(iter);
964  if(!ENDP(curr))
967  block_created=true;
968  }
969  else
970  curr=CONS(STATEMENT,st,curr);
971  } while(!ENDP(iter)&&!block_created);
972  if(!block_created) {
973  curr=gen_nreverse(curr);
975  }
976  }
980  }
981 }
982 
984  if(statement_block_p(s)) {
985  list iter,prev=NIL;
986  for(iter=statement_block(s);!ENDP(iter) && declaration_statement_p(STATEMENT(CAR(iter))); POP(iter) ) {
987  prev=iter;
988  }
989  if(!ENDP(iter) && !ENDP(prev) ) {
990  CDR(prev)=NIL;
991  statement tail = make_block_statement(iter);
992  /* is there a tail return ? */
993  list iter2,prev2=NIL;
994  for(iter2=iter;!ENDP(iter2) && !return_statement_p(STATEMENT(CAR(iter2))); POP(iter2) ) {
995  prev2=iter2;
996  }
997  if(!ENDP(iter2) && !ENDP(prev2) ) { /* yes there is */
998  CDR(prev2)=NIL;
999  statement rtail = make_block_statement(iter2);
1000  insert_statement_no_matter_what(STATEMENT(CAR(prev)),tail,false);
1001  insert_statement_no_matter_what(STATEMENT(CAR(prev)),rtail,false);
1002  }
1003  else {
1004  insert_statement_no_matter_what(STATEMENT(CAR(prev)),tail,false);
1005  }
1006  }
1007  else {
1008  /* is there a tail return ? */
1009  list iter2,prev2=NIL;
1010  for(iter2=iter=statement_block(s);!ENDP(iter2) && !return_statement_p(STATEMENT(CAR(iter2))); POP(iter2) ) {
1011  prev2=iter2;
1012  }
1013  if(!ENDP(iter2) && !ENDP(prev2) ) { /* yes there is */
1014  CDR(prev2)=NIL;
1015  statement rtail = make_block_statement(iter2);
1016  /* not using insert_statement because it is too smart ! we want to keep a block*/
1018  }
1019  }
1020  }
1021 }
1022 
1023 bool simdizer_init(const char * module_name)
1024 {
1025  /* get the resources */
1028 
1029  /* normalize blocks */
1031 
1032  /* then split blocks containing declarations statement */
1034 
1035  /* then split blocks containing labeled statement */
1037 
1038  /* sort commutative operators */
1040 
1043 
1044  /* reset */
1047 
1048  return true;
1049 
1050 }
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
bool statement_consistent_p(statement p)
Definition: ri.c:2195
void free_expression(expression p)
Definition: ri.c:853
static graph dependence_graph
Definition: delay.c:93
void remove_preferences(void *)
delay.c
Definition: delay.c:89
static FILE * out
Definition: alias_check.c:128
@ INT
Definition: atomic.c:48
callees compute_callees(const statement stat)
Recompute the callees of a module statement.
Definition: callgraph.c:355
bool clean_up_sequences(statement s)
Recursively clean up the statement sequences by fusing them if possible and by removing useless one.
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
static list blocks
lisp of loops
#define conflict_sink(x)
Definition: dg.h:167
#define cone_levels(x)
Definition: dg.h:128
#define CONFLICT(x)
CONFLICT.
Definition: dg.h:134
#define dg_arc_label_conflicts(x)
Definition: dg.h:201
#define cone_undefined_p(x)
Definition: dg.h:105
#define conflict_source(x)
Definition: dg.h:165
#define conflict_cone(x)
Definition: dg.h:169
list region_intersection(region reg1, region reg2)
Intersection :
list effects_read_effects(list)
list load_proper_rw_effects_list(statement)
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
list effects_write_effects(list)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_read_p(eff)
#define effect_scalar_p(eff) entity_scalar_p(effect_entity(eff))
struct _newgen_struct_statement_effects_ * statement_effects
Definition: effects.h:210
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
#define LIST(x)
Definition: genC.h:93
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void gen_full_free_list(list l)
Definition: genClib.c:1023
void free(void *)
#define successor_vertex(x)
Definition: graph.h:118
#define successor_arc_label(x)
Definition: graph.h:116
struct _newgen_struct_graph_ * graph
Definition: graph.h:31
#define vertex_successors(x)
Definition: graph.h:154
#define SUCCESSOR(x)
SUCCESSOR.
Definition: graph.h:86
#define graph_vertices(x)
Definition: graph.h:82
#define VERTEX(x)
VERTEX.
Definition: graph.h:122
void set_conflict_testing_properties()
conflicts.c
Definition: conflicts.c:68
bool effects_may_conflict_p(effect eff1, effect eff2)
Check if two effect may conflict @description Two effects may conflict if their abstract two location...
Definition: conflicts.c:162
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
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_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
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
list gen_append(list l1, const list l2)
Definition: list.c:471
void gen_sort_list(list l, gen_cmp_func_t compare)
Sorts a list of gen_chunks in place, to avoid allocations...
Definition: list.c:796
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
list statement_block(statement)
Get the list of block statements of a statement sequence.
Definition: statement.c:1338
bool statement_call_p(statement)
Definition: statement.c:364
bool return_statement_p(statement)
Test if a statement is a C or Fortran "return".
Definition: statement.c:172
void pop_generated_variable_commenter(void)
Definition: statement.c:2623
void insert_statement_no_matter_what(statement, statement, bool)
Break the IR consistency or, at the very least, do not insert new declarations at the usual place,...
Definition: statement.c:2581
void push_generated_variable_commenter(string(*)(entity))
Definition: statement.c:2616
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
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_update(hash_table htp, const void *key, const void *val)
update key->val in htp, that MUST be pre-existent.
Definition: hash.c:491
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
void * hash_del(hash_table htp, const void *key)
this function removes from the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:439
list hash_get_default_empty_list(const hash_table h, const void *k)
Like hash_get() but returns an empty list instead of HASH_UNDEFINED_VALUE when a key is not found.
Definition: hash.c:475
void * hash_table_scan(hash_table htp, void *hentryp_arg, void **pkey, void **pval)
Definition: hash.c:844
void hash_table_clear(hash_table htp)
Clears all entries of a hash table HTP.
Definition: hash.c:305
statement vertex_to_statement(vertex v)
Vertex_to_statement looks for the statement that is pointed to by vertex v.
Definition: util.c:45
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define asprintf
Definition: misc-local.h:225
#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 debug_off()
Definition: misc-local.h:160
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
@ 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 hash_table_undefined_p(h)
Definition: newgen_hash.h:50
#define hash_table_undefined
Value of an undefined hash_table.
Definition: newgen_hash.h:49
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26
#define hash_table_empty_p(htp)
Definition: newgen_hash.h:58
bool set_empty_p(const set)
tell whether set s is empty.
Definition: set.c:367
set set_assign_list(set, const list)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474
set set_intersection(set, const set, const set)
Definition: set.c:229
list set_to_sorted_list(const set, gen_cmp_func_t)
Definition: set.c:447
set set_difference(set, const set, const set)
Definition: set.c:256
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
struct cons * list
Definition: newgen_types.h:106
void reset_simd_operator_mappings()
Definition: operatorid.c:48
void set_simd_operator_mappings(void *m)
operatorid.c
Definition: operatorid.c:43
hash_table set_ordering_to_statement(statement s)
To be used instead of initialize_ordering_to_statement() to make sure that the hash table ots is in s...
Definition: ordering.c:172
void reset_ordering_to_statement(void)
Reset the mapping from ordering to statement.
Definition: ordering.c:185
bool sac_expression_reduction_p(expression e)
reductions.c
Definition: reductions.c:55
string reference_to_string(reference r)
Definition: expression.c:87
list Words_Call(call obj, int precedence, bool leftmost, bool is_a_subroutine)
Definition: misc.c:2597
#define print_region(x)
Definition: print.c:343
void print_statements(list)
Definition: statement.c:103
string basic_to_string(basic)
Definition: type.c:87
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define binary_call_rhs(c)
#define statement_block_p(stat)
#define expression_scalar_p(e)
#define binary_call_lhs(c)
#define make_statement_list(stats...)
easy list constructor
bool commutative_call_p(call c)
Test if we are allowed to commute operations.
Definition: entity.c:2661
int compare_entities(const entity *pe1, const entity *pe2)
Comparison function for qsort.
Definition: entity.c:1328
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
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
bool entity_empty_label_p(entity e)
Definition: entity.c:666
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
expression reference_to_expression(reference r)
Definition: expression.c:196
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
bool extended_expression_constant_p(expression exp)
Returns true if the value of the expression does not depend syntactically on the current store.
Definition: expression.c:2461
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
struct _newgen_struct_value_ * value
Definition: ri.h:455
#define reference_variable(x)
Definition: ri.h:2326
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define instruction_undefined
Definition: ri.h:1454
#define statement_label(x)
Definition: ri.h:2450
#define expression_undefined
Definition: ri.h:1223
#define sequence_statements(x)
Definition: ri.h:2360
#define instruction_sequence(x)
Definition: ri.h:1514
#define instruction_call_p(x)
Definition: ri.h:1527
#define expression_undefined_p(x)
Definition: ri.h:1224
#define statement_instruction(x)
Definition: ri.h:2458
#define call_arguments(x)
Definition: ri.h:711
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
int vertex_ordering(vertex)
Definition: util.c:51
simdstatement make_simd_statements(set opkinds, list statements)
Definition: codegen.c:1193
list generate_simd_code(simdstatement ssi, float *simdCost)
Definition: codegen.c:1325
bool expression_reference_or_field_p(expression e)
Definition: codegen.c:192
bool simd_vector_entity_p(entity e)
Definition: codegen.c:197
bool sac_aligned_entity_p(entity e)
Definition: codegen.c:646
void init_vector_to_expressions()
codegen.c
Definition: codegen.c:59
void invalidate_expressions_in_statement(statement s)
Definition: codegen.c:162
void reset_vector_to_expressions()
Definition: codegen.c:64
expression distance_between_expression(const expression exp0, const expression exp1)
computes the distance betwwen two expression
Definition: codegen.c:419
void reset_simd_treematch(void)
Definition: treematch.c:52
void set_simd_treematch(matchTree)
treematch.c
Definition: treematch.c:46
void simd_reset_finalArgType(void)
Definition: treematch.c:61
list match_statement(statement)
return a list of matching statements
Definition: treematch.c:237
bool simd_check_argType(void)
Definition: treematch.c:87
void simd_fill_finalArgType(statement)
Definition: treematch.c:77
void simd_fill_curArgType(statement)
Definition: treematch.c:82
#define opcode_vectorSize(x)
Definition: sac_private.h:291
#define MATCH(x)
MATCH.
Definition: sac_private.h:221
#define match_type(x)
Definition: sac_private.h:251
#define simdstatement_opcode(x)
Definition: sac_private.h:491
#define simdstatement_undefined_p(x)
Definition: sac_private.h:466
#define match_undefined
Definition: sac_private.h:227
#define opcodeClass_name(x)
Definition: sac_private.h:534
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
char * strdup()
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
match get_statement_match_of_kind(statement s, opcodeClass kind)
simdizer.c
Definition: simdizer.c:101
static void do_split_decl_block_statements(statement s)
Definition: simdizer.c:983
static void simdize_simple_statements(statement s, simdizer_context *sc)
Definition: simdizer.c:740
static void reset_statement_origin()
Definition: simdizer.c:413
static set extract_non_conflicting_statements(statement s, list tail)
Definition: simdizer.c:257
static hash_table equivalence_table
Definition: simdizer.c:129
static bool conflict_is_a_real_conflict_p(conflict c, statement source, statement sink, size_t loop_level)
this code is here because levels information seems inaccurate so it checks all the possible conflict ...
Definition: simdizer.c:138
static list simdize_simple_statements_pass2(list seq, float *simdCost)
Definition: simdizer.c:611
bool simdizer_init(const char *module_name)
Definition: simdizer.c:1023
static bool sac_statement_to_expressions_gather(expression e, list *l)
Definition: simdizer.c:310
#define NOSWAP_ARGUMENTS(c)
static bool incr_counter(loop l, simdizer_context *sc)
Definition: simdizer.c:838
static void do_simdizer_init(call c)
Definition: simdizer.c:907
static void decr_counter(loop l, simdizer_context *sc)
Definition: simdizer.c:843
static void set_statement_origin(statement s)
Definition: simdizer.c:412
static list get_statement_matches(statement s)
Definition: simdizer.c:90
static set get_statement_matching_types(statement s)
Definition: simdizer.c:119
static void free_statement_equivalence_table()
Definition: simdizer.c:250
static void free_statement_matches_map()
Definition: simdizer.c:81
static bool simd_simple_sequence_filter(statement s, __attribute__((unused)) simdizer_context *sc)
Definition: simdizer.c:816
static int compare_statements_on_ordering(const void *v0, const void *v1)
Definition: simdizer.c:365
static list order_isomorphic_statements(set s)
Definition: simdizer.c:508
static int compare_statements_on_distance_to_origin(const void *ps0, const void *ps1)
Definition: simdizer.c:415
statement sac_current_block
Definition: simdizer.c:722
#define SWAP_ARGUMENTS(c)
static void init_statement_equivalence_table(list *l, graph dependence_graph, size_t loop_level)
Definition: simdizer.c:519
static set extract_matching_statements(statement s, set stats, set *matches)
Definition: simdizer.c:279
static int compare_list_from_length(const void *v0, const void *v1)
Definition: simdizer.c:469
static hash_table matches
Definition: simdizer.c:60
static bool successor_only_has_rr_conflict_p(vertex v, successor su, size_t loop_level)
Definition: simdizer.c:195
static void init_statement_matches_map(list l)
Definition: simdizer.c:66
static statement origin
Definition: simdizer.c:411
static bool comparable_statements_on_distance_p(statement s0, statement s1)
Definition: simdizer.c:344
static list order_isomorphic_statements_list(list ordered)
Definition: simdizer.c:478
bool simdizer(char *mod_name)
Definition: simdizer.c:854
string sac_commenter(entity e)
Definition: simdizer.c:821
static void do_split_block_statements(statement s)
Definition: simdizer.c:953
static list sac_statement_to_expressions(statement s)
Definition: simdizer.c:320
instruction sac_real_current_instruction
Definition: simdizer.c:723
#define intptr_t
Definition: stdint.in.h:294
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
size_t nb_enclosing_loops
Definition: simdizer.c:727
string words_to_string(cons *lw)
Definition: print.c:211
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207