PIPS
codegen.c
Go to the documentation of this file.
1 /*
2 
3  $Id: codegen.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 #include "genC.h"
28 #include "linear.h"
29 #include "ri.h"
30 #include "effects.h"
31 
32 #include "resources.h"
33 
34 #include "misc.h"
35 #include "ri-util.h"
36 #include "prettyprint.h"
37 #include "effects-util.h"
38 
39 #include "effects-generic.h"
40 #include "text-util.h"
41 #include "effects-simple.h"
42 
43 #include "sac.h"
44 #include "patterns.h"
45 
46 #include "properties.h"
47 
48 #include "misc.h"
49 #include <ctype.h>
50 #include <stdlib.h>
51 
52 #define MAX_PACK 16
53 #define VECTOR_POSTFIX "vec"
54 
55 
56 static float gSimdCost;
57 
60 {
63 }
65 {
69 }
70 
71 static entity do_expressions_to_vector(list expressions) {
72  void * hiter = NULL;
73  entity key;
74  list value;
75  while( (hiter = hash_table_scan(vector_to_expressions,hiter,(void**)&key,(void**)&value) ))
76  {
78  return key;
79  }
80  return entity_undefined;
81 }
82 
84 {
85  pips_assert("entity is ok",entity_consistent_p(e));
86  /* create the enw vector */
87  FOREACH(EXPRESSION,exp,exps) pips_assert("expressions are ok",expression_consistent_p(exp));
88  /* remove the old ones */
90  FOREACH(EXPRESSION,exp,exps) {
91  for(list iter=expressions;!ENDP(iter);POP(iter)) {
92  expression * piter = (expression*) REFCAR(iter);
93  if(expression_equal_p(exp,*piter)) /* invalidate */ {
94  free_expression(*piter);
95  *piter=expression_undefined;
96  }
97  }
98  }
99  }
101 }
102 
103 /* This function will create the permutations indexes that will allow
104  the creation of exp_final from exp_loaded with a shuffle */
105 static void make_permutations_indexes(list exp_final, list exp_loaded, int* perms)
106 {
107  int index_loaded = 0;
108  FOREACH(EXPRESSION,ef,exp_loaded) {
109  int index_perm = 0;
110  FOREACH(EXPRESSION,el,exp_final) {
111  if (expression_equal_p(ef,el)) {
112  perms[index_loaded] = index_perm;
113  break;
114  }
115  index_perm++;
116  }
117  index_loaded++;
118  }
119 }
120 
121 static entity try_all_permutations(list expressions, list remainder, list exp_org, statement* shuffle,int *perms)
122 {
124  list tmp = gen_copy_seq(expressions);
125  list rtmp = gen_copy_seq(remainder);
126  gen_remove_once(&rtmp,exp);
127  list newexp = CONS(EXPRESSION,exp,tmp);
128  entity out = try_all_permutations(newexp,rtmp,exp_org,shuffle,perms);
129  gen_free_list(newexp);
130  gen_free_list(rtmp);
131  if(!entity_undefined_p(out))
132  return out;
133  }
134  if(ENDP(remainder)) {
135  entity out = do_expressions_to_vector(expressions);
136  if(!entity_undefined_p(out))
137  {
138  make_permutations_indexes(exp_org, expressions, perms);
139  *shuffle=make_shuffle_statement(&out,expressions,perms);
140  }
141  return out;
142  }
143  return entity_undefined;
144 }
145 
147 {
148  /* try all possible permutations, well only invert from now on */
149  entity out = do_expressions_to_vector(expressions);
150  size_t nb_expressions = gen_length(expressions);
151  if(!entity_undefined_p(out)) return out;
152  /* give up if there are two may permutations to try out */
153  else if(nb_expressions <= 8 ) {
154  int perm [1+nb_expressions];
155  perm[nb_expressions]=0;
156  return try_all_permutations(NIL,expressions,expressions,shuffle,perm);
157  }
158  else
159  return entity_undefined;
160 }
161 
163 {
165  void * hiter = NULL;
166  entity key;
167  list value;
168  list purge = NIL;
169  while( (hiter = hash_table_scan(vector_to_expressions,hiter,(void**)&key,(void**)&value) ))
170  {
171  bool invalidate=false;
173  {
175  {
176  FOREACH(EFFECT,eff,effects)
178  {
180  break;
181  }
182  }
183  if(invalidate) break;
184  }
185  if(invalidate) purge=CONS(ENTITY,key,purge);
186  }
187  FOREACH(ENTITY,e,purge)
189  gen_free_list(purge);
190 }
191 
193 {
195 }
196 
198 {
199  return
202  && !entity_scalar_p(e);
203  ;
204 }
205 /* expression is an simd vector
206  * if it is a reference array
207  * containing VECTOR_POSTFIX in its name
208  */
209 static
211 {
212  syntax s = expression_syntax(e);
214 }
215 
216 
217 /*
218  This function return the basic corresponding to the argNum-th
219  argument of opcode oc
220  */
221 static enum basic_utype get_basic_from_opcode(opcode oc, int argNum)
222 {
223  int type = INT(gen_nth(argNum, opcode_argType(oc)));
224 
225  switch(type)
226  {
227  case QI_REF_TOK:
228  case HI_REF_TOK:
229  case SI_REF_TOK:
230  case DI_REF_TOK:
231  return is_basic_int;
232  case SF_REF_TOK:
233  case DF_REF_TOK:
234  return is_basic_float;
235  case SC_REF_TOK:
236  case DC_REF_TOK:
237  return is_basic_complex;
238  default:
239  pips_internal_error("subword size unknown.");
240  }
241 
242  return is_basic_int;
243 }
244 
245 
247 {
248  int type = INT(gen_nth(argNum, opcode_argType(oc)));
249 
250  switch(type)
251  {
252  case QI_REF_TOK:
253  return 8;
254  case HI_REF_TOK:
255  return 16;
256  case SI_REF_TOK:
257  return 32;
258  case DI_REF_TOK:
259  return 64;
260  case SF_REF_TOK:
261  return 32;
262  case DF_REF_TOK:
263  return 64;
264  case SC_REF_TOK:
265  return 64;
266  case DC_REF_TOK:
267  return 128;
268  default:
269  pips_internal_error("subword size unknown.");
270  }
271 
272  return 8;
273 }
274 
275 /* auto-guess vector size */
276 opcode generate_opcode(string name, list types, float cost)
277 {
278  intptr_t elem_size=0,vector_size = get_int_property("SAC_SIMD_REGISTER_WIDTH");
279  opcode oc = make_opcode(name,vector_size,types,cost);
280  int n = gen_length(types);
281  for(int i=0; i<n;i++)
282  {
283  int curr = get_subwordSize_from_opcode(oc,i);
284  if(curr > elem_size) elem_size=curr;
285  }
286  opcode_vectorSize(oc)/=elem_size;
287  if( opcode_vectorSize(oc) * elem_size !=get_int_property("SAC_SIMD_REGISTER_WIDTH"))
288  pips_user_warning("SAC_SIMD_REGISTER_WIDTH and description of %s leads "
289  "to partially filled register\n", name);
290  return oc;
291 }
292 
293 /* Computes the optimal opcode for simdizing 'argc' statements of the
294  * 'kind' operation, applied to the 'args' arguments
295  * it is a greedy matching, so it supposes the list of args is in the best order for us
296  */
297 static opcode get_optimal_opcode(opcodeClass kind, int argc, list* args)
298 {
299  int i;
300  opcode best;
301  /* Based on the available implementations of the operation, decide
302  * how many statements to pack together
303  */
304  best = opcode_undefined;
306  {
307  bool bTagDiff = false;
308  int mwidth = 0;
309 
310  for(i = 0; i < argc; i++)
311  {
312  int count = 0;
313  //int width = mwidth=0;
314  int width = 0;
315  mwidth=0;
316 
317  FOREACH(EXPRESSION,arg,args[i])
318  {
319 
321  {
322  count++;
323  continue;
324  }
325 
326  basic bas = basic_of_expression(arg);
327  enum basic_utype bas_pattern = get_basic_from_opcode(oc, count);
328 
329  if(!basic_overloaded_p(bas) && bas_pattern!=basic_tag(bas)
330  /*&& !(bas_pattern == is_basic_float && basic_int_p(bas))*/) /* allow the promotion of an int
331  to a float */
332 
333  {
334  bTagDiff = true;
335  free_basic(bas);
336  break;
337  }
338 
339  width = SizeOfElements(bas);
340  if(width>mwidth)mwidth=width;
341  free_basic(bas);
342 
343  if(width > get_subwordSize_from_opcode(oc, count))
344  {
345  bTagDiff = true;
346  break;
347  }
348 
349  count++;
350 
351  }
352  }
353 
354  if ( (!bTagDiff) &&
355  (opcode_vectorSize(oc) <= argc) &&
356  (opcode_vectorSize(oc)*mwidth*8 == get_int_property("SAC_SIMD_REGISTER_WIDTH"))) {
357  best = oc;
358  }
359  }
360 
361  return best;
362 }
363 
364 
365 /**
366  * computes the offset between an entity and its reference
367  *
368  * @param r
369  *
370  * @return an expression of the offset, in octets
371  */
372 static
374 {
375  if(get_bool_property("SIMD_FORTRAN_MEM_ORGANISATION")) {
376  reference cr = copy_reference(r);
379  free_reference(cr);
380  return out;
381  }
382  else
383  return reference_offset(r);
384 }
385 
387 {
388 
389  entity parent_struct = entity_field_to_entity_struct(e);
390  list fields = type_struct(entity_type(parent_struct));
392  FOREACH(ENTITY,field,fields)
393  if(same_entity_p(field,e)) break;
394  else {
399  );
400  }
401  return offset;
402 }
403 
405 {
406  if(same_entity_p(e0,e1))
407  return int_to_expression(0);
408  else if( entity_field_p(e0) && entity_field_p(e1) && same_struct_entity_p(e0,e1) )
410  else
411  return expression_undefined;
412 }
413 
414 /**
415  * computes the distance betwwen two expression
416  *
417  * @return expression_undefined if not comparable, an expression of the distance otherwise
418  */
420 {
421  bool eval_sizeof = get_bool_property("EVAL_SIZEOF");
422  set_bool_property("EVAL_SIZEOF",true);
425  {
426  reference r0 = expression_reference(exp0),
427  r1 = expression_reference(exp1);
428 
429  /* reference with different variables have an infinite distance */
430  entity e0 = reference_variable(r0),
431  e1 = reference_variable(r1);
432  expression edistance = distance_between_entity(e0,e1);
433  if(!expression_undefined_p(edistance))
434  {
435  basic b = basic_of_reference(r0);
436  expression offset0 = sreference_offset(r0),
437  offset1 = sreference_offset(r1);
438  expression distance = make_op_exp(MINUS_OPERATOR_NAME,offset1,offset0);
440  distance,int_to_expression(SizeOfElements(b)));
441  free_basic(b);
442  result= make_op_exp(PLUS_OPERATOR_NAME,distance,edistance);
443  }
444  }
445  else if (expression_field_p(exp0) && expression_field_p(exp1))
446  {
448  str1 = binary_call_lhs(expression_call(exp1));
449  expression lhs_distance = distance_between_expression(str0,str1);
451  if(!expression_undefined_p(lhs_distance) && !expression_undefined_p(rhs_distance))
452  result = make_op_exp(MINUS_OPERATOR_NAME,lhs_distance,rhs_distance);
453  }
454  set_bool_property("EVAL_SIZEOF",eval_sizeof);
455  //maxima_simplify(&result);
456  simplify_expression(&result);
457  return result;
458 }
459 
460 /*
461  This function returns true if e0 and e1 have a distance of 1 + lastOffset
462  */
463 static bool consecutive_expression_p(expression e0, int lastOffset, expression e1)
464 {
465  bool result=false;
466  basic b = basic_of_expression(e0);
467  int ref_offset = SizeOfElements(b);
468  free_basic(b);
469  expression distance = distance_between_expression(e0,e1);
470  if( !expression_undefined_p(distance) )
471  {
472  intptr_t idistance;
473  NORMALIZE_EXPRESSION(distance);
474  if((result=expression_integer_value(distance,&idistance)))
475  {
476  pips_debug(3,"distance between %s and %s is %"PRIdPTR"\n",
478  expression_to_string(e1),idistance);
479  result= idistance == ref_offset+ref_offset*lastOffset;
480  }
481  else {
482  pips_debug(3,"distance between %s and %s is too complexd\n",
484  }
485  free_expression(distance);
486  }
487  return result;
488 }
489 
490 /*
491  This function returns the vector type string by reading the name of the first
492  element of lExp
493  */
494 static string get_simd_vector_type(list lExp)
495 {
496  string result = NULL;
497 
498  FOREACH(EXPRESSION, exp,lExp)
499  {
502  exp))));
503 
504  if(type_variable_p(t))
505  {
507  pips_assert("searching in a sac vector",basic_typedef_p(bas));
508 
509  result = strdup(entity_name(basic_typedef(bas)));
510  /* switch to upper cases... */
511  result=strupper(result,result);
512 
513  break;
514 
515  }
516  }
517 
518  return result;
519 }
520 
521 /*
522  This function returns the name of a vector from the data inside it
523  */
524 static string get_vect_name_from_data(int argc, list exps)
525 {
526  char prefix[5];
527  string result;
528  int itemSize;
529 
530  basic bas = basic_of_expressions(exps,true);
531 
532  prefix[0] = 'v';
533  prefix[1] = '0'+argc;
534 
535  switch(basic_tag(bas))
536  {
537  case is_basic_int:
538  prefix[3] = 'i';
539  break;
540 
541  case is_basic_float:
542  prefix[3] = 'f';
543  break;
544 
545  case is_basic_logical:
546  prefix[3] = 'i';
547  break;
548  case is_basic_complex:
549  prefix[3] = 'c';
550  break;
551 
552  default:
553  free_basic(bas);
554  return strdup("");
555  break;
556  }
557  itemSize=8*SizeOfElements(bas);
558  free_basic(bas);
559 
560  switch(itemSize)
561  {
562  case 8: prefix[2] = 'q'; break;
563  case 16: prefix[2] = 'h'; break;
564  case 32: prefix[2] = 's'; break;
565  case 64: prefix[2] = 'd'; break;
566  default:pips_internal_error("case not handled");
567  }
568 
569  prefix[4] = 0;
570 
571  result = strdup(prefix);
572 
573  /* switch to upper cases... */
574  result=strupper(result,result);
575 
576  return result;
577 }
578 
579 static
581 {
583  {
585  {
586  syntax syn = expression_syntax(e);
589  make_call(
593  )
594  )
595  )
596  );
597  }
598  }
599 
600 }
601 
602 static statement make_exec_statement_from_name(string ename, list args)
603 {
604  /* SG: ugly patch to make sure fortran's parameter passing and c's are respected */
605  entity exec_function = module_name_to_runtime_entity(ename);
606  if( c_module_p(exec_function) )
607  {
608  string pattern0;
609  asprintf(&pattern0,"%s" SIMD_GENERIC_SUFFIX,get_string_property("ACCEL_LOAD"));
610  string pattern1;
611  asprintf(&pattern1,"%s" SIMD_BROADCAST_SUFFIX,get_string_property("ACCEL_LOAD"));
612  if( strstr(ename,pattern0) )
614  else if( strstr(ename,pattern1) )
616  else {
618  }
619  free(pattern0);
620  free(pattern1);
621  }
623 }
625 {
626  return make_exec_statement_from_name( opcode_name(oc) , args );
627 }
628 
629 static basic get_typedefed_array(const char * type_name, basic b, list dims) {
630  entity e = FindEntity(TOP_LEVEL_MODULE_NAME,type_name);
631  if(entity_undefined_p(e)) {
635  b,
636  dims,NIL
637  )
638  );
641  }
642  return make_basic_typedef(e);
643 }
644 
645 #define SAC_ALIGNED_VECTOR_NAME "pdata"
647 {
649 }
650 
652 {
654  {
657  }
658  return false;
659 }
660 /*
661  This function creates a simd vector.
662  */
663 static entity make_new_simd_vector_with_prefix(int itemSize, int nbItems, enum basic_utype basicTag, const char *vname)
664 {
665  //extern list integer_entities, real_entities, double_entities;
666 
667  basic simdVector;
668 
669  entity new_ent, mod_ent;
670  char prefix[6]={ same_string_p(vname,VECTOR_POSTFIX)?'v':'a', '0', '\0', '\0', '\0', '\0' },
671  num[1 + sizeof(VECTOR_POSTFIX) + 3 ],
672  name[sizeof(prefix)+sizeof(num)+1];
673  static int number = 0;
674 
676 
677  /* build the variable prefix code, which is in fact also the type */
678  prefix[1] += nbItems;
679  switch(itemSize)
680  {
681  case 8: prefix[2] = 'q'; break;
682  case 16: prefix[2] = 'h'; break;
683  case 32: prefix[2] = 's'; break;
684  case 64: prefix[2] = 'd'; break;
685  }
686 
687 
688  switch(basicTag)
689  {
690  case is_basic_int:
691  simdVector = make_basic_int(itemSize/8);
692  prefix[3] = 'i';
693  break;
694 
695  case is_basic_float:
696  simdVector = make_basic_float(itemSize/8);
697  prefix[3] = 'f';
698  break;
699 
700  default:
701  simdVector = make_basic_int(itemSize/8);
702  prefix[3] = 'i';
703  break;
704  }
705 
706  pips_assert("buffer doesnot overflow",number<10000);
707  sprintf(name, "%s%u", vname,number++);
708  list lis=CONS(DIMENSION,
710  int_to_expression(nbItems-1),
711  NIL),
712  NIL);
713 
714  basic typedefedSimdVector = get_typedefed_array(prefix,simdVector,lis);
715 
716  new_ent = make_new_scalar_variable_with_prefix(name, mod_ent , typedefedSimdVector);
717 
718 #if 0
719  string type_name = strdup(concatenate(prefix,"_struct", (char *) NULL));
720  entity str_type = FindOrCreateEntity(entity_local_name(mod_ent), type_name);
721  entity_type(str_type) =make_type_variable(make_variable(simdVector,NIL,NIL));
722 
724  entity_type(str_dec) = entity_type(str_type);
725 #endif
726 
727  if( same_string_p(vname, VECTOR_POSTFIX))
729  else
730  AddEntityToCurrentModule(new_ent);
731 
732  return new_ent;
733 }
734 static entity make_new_simd_vector(int itemSize, int nbItems, enum basic_utype basicTag)
735 {
736  return make_new_simd_vector_with_prefix(itemSize, nbItems, basicTag, VECTOR_POSTFIX);
737 }
738 
739 /* This function change the "load/store type" to XX_TO_XX if a conversion
740  * is needed. It returns true if a change is made, and the pointer
741  * *lsType must be freed after being used. */
742 static bool loadstore_type_conversion_string(int argc, list args, string* lsType, bool isLoad)
743 {
744  string lsTypeTmp = (char*)local_name(get_simd_vector_type(args));
745  string realVectName = get_vect_name_from_data(argc, CDR(args));
746  if (!same_string_p(realVectName, lsTypeTmp))
747  {
748  entity forged_array = entity_undefined;
749  FOREACH(EXPRESSION,arg,CDR(args)) {
750  if(expression_reference_p(arg)) {
752  entity var = forged_array=reference_variable(r);
753  if(strncmp(entity_user_name(var),
755  sizeof(SAC_ALIGNED_VECTOR_NAME)-1)!=0) {
756  forged_array=entity_undefined;
757  break;
758  }
759  else if(entity_undefined_p(forged_array)) {
760  forged_array = var;
761  }
762  else if(!same_entity_p(forged_array,var)) {
763  forged_array=entity_undefined;
764  break;
765  }
766  }
767  }
768  /* we can handle this situation :p */
769  if(!entity_undefined_p(forged_array)) {
770  expression exp = EXPRESSION(CAR(args));
773  variable v = type_variable(t);
779  );
781  entity_initial(new) = copy_value(entity_initial(forged_array));
782  FOREACH(EXPRESSION,ex,CDR(args))
783  replace_entity(ex,forged_array,new);
784  }
785  else {
786  asprintf(lsType,"%s_TO_%s",
787  isLoad?realVectName:lsTypeTmp,
788  isLoad?lsTypeTmp:realVectName);
789  return true;
790  }
791  }
792  return false;
793 }
794 
795 static statement make_loadsave_statement(int argc, list args, bool isLoad)
796 {
797  enum {
798  CONSEC_REFS,
799  MASKED_CONSEC_REFS,
800  CONSTANT,
801  OTHER,
802  BROADCAST
803  } argsType;
804  static char *funcNames[6][2] = { { NULL,NULL},{NULL,NULL},{NULL,NULL},{NULL,NULL}};
805  if(!funcNames[0][0]) {
806  asprintf(&funcNames[0][0],"%s_",get_string_property("ACCEL_STORE"));
807  asprintf(&funcNames[0][1],"%s_",get_string_property("ACCEL_LOAD"));
808  asprintf(&funcNames[1][0],"%s"SIMD_MASKED_SUFFIX"_",get_string_property("ACCEL_STORE"));
809  asprintf(&funcNames[1][1],"%s"SIMD_MASKED_SUFFIX"_",get_string_property("ACCEL_LOAD"));
810  asprintf(&funcNames[2][0],"%s"SIMD_CONSTANT_SUFFIX"_",get_string_property("ACCEL_STORE"));
811  asprintf(&funcNames[2][1],"%s"SIMD_CONSTANT_SUFFIX"_",get_string_property("ACCEL_LOAD"));
812  asprintf(&funcNames[3][0],"%s"SIMD_GENERIC_SUFFIX"_",get_string_property("ACCEL_STORE"));
813  asprintf(&funcNames[3][1],"%s"SIMD_GENERIC_SUFFIX"_",get_string_property("ACCEL_LOAD"));
814  asprintf(&funcNames[4][0],"%s"SIMD_BROADCAST_SUFFIX"_",get_string_property("ACCEL_STORE"));
815  asprintf(&funcNames[4][1],"%s"SIMD_BROADCAST_SUFFIX"_",get_string_property("ACCEL_LOAD"));
816  }
817  int lastOffset = 0;
818  char *functionName;
819 
820  string lsType = (char*)local_name(get_simd_vector_type(args));
821  bool all_scalar = false;
822  bool all_same_aligned_ref = false;
823  bool all_same_ref = true;
824 
825  /* the function should not be called with an empty arguments list */
826  assert((argc > 1) && (args != NIL));
827 
828  /* first, find out if the arguments are:
829  * - consecutive references to the same array
830  * - all constant
831  * - or any other situation
832  */
834 
835  /* classify according to the second element
836  * (first one should be the SIMD vector) */
837  expression exp = EXPRESSION(CAR(CDR(args)));
839  if (expression_constant_p(real_exp))
840  {
841  argsType = CONSTANT;
842  all_scalar = true;
843  }
844  // If e is a reference expression, let's analyse this reference
845  else if (expression_reference_p(real_exp))
846  {
847  argsType = CONSEC_REFS;
848  fstExp = exp;
849  all_scalar = expression_scalar_p(exp); /* and not real_exp ! */
850  all_same_aligned_ref = sac_aligned_expression_p(exp);
851  }
852  else
853  argsType = OTHER;
854 
855  /* now verify the estimation on the first element is correct, and update
856  * parameters needed later */
857  for(list iter = CDR(CDR(args));!ENDP(iter);POP(iter))
858  {
859  expression e = EXPRESSION(CAR(iter));
861  if(expression_undefined_p(fstExp) ||! same_expression_p(fstExp,real_e))
862  all_same_ref=false;
863 
864  if (argsType == OTHER)
865  {
866  all_scalar = all_scalar && expression_scalar_p(e) &&
868  continue;
869  }
870  else if (argsType == CONSTANT)
871  {
872  if (!expression_constant_p(real_e))
873  {
874  argsType = OTHER;
875  all_scalar = all_scalar && expression_scalar_p(e) &&
877  continue;
878  }
879  }
880  else if (argsType == CONSEC_REFS)
881  {
882  // If e is a reference expression, let's analyse this reference
883  // and see if e is consecutive to the previous references
884  if ( (expression_reference_p(real_e)) &&
885  (consecutive_expression_p(fstExp, lastOffset, e)) )
886  {
887  ++lastOffset;
888  all_scalar=false;
889  }
890  else
891  {
892  argsType = OTHER;
893  all_same_aligned_ref = all_same_aligned_ref && same_expression_p(e,fstExp);
894  all_scalar = all_scalar && expression_scalar_p(e) &&
896  continue;
897  }
898  }
899  }
900  /* eventually, we have four times the same reference loaded.
901  * In that case, use a broadcast call */
902  if(all_same_ref && !expression_undefined_p(fstExp) ) {
903  pips_assert("all reference are the same, so it's an 'other' kind\n",argsType==OTHER);
904  argsType = BROADCAST;
905  }
906  /* first pass of analysis is done
907  * we may have found that we have no consecutive references
908  * but a set of scalar
909  * if so, we should replace those scalars by appropriate array
910  */
911  else if(all_scalar)
912  {
914  size_t nbargs=gen_length(CDR(args));
915  basic shared_basic = basic_of_expressions(CDR(args),true);
916  char * tname =strdup(get_vect_name_from_data(nbargs,CDR(args)));
917  tname=strlower(tname,tname);
918  tname[0]='a';/*array*/
919 
923  )
924  );
925  free(tname);
926  AddEntityToCurrentModule(scalar_holder);
927  int index=0;
928  list inits = NIL;
929  list replacements = NIL;
930  for(list iter = CDR(args); !ENDP(iter) ; POP(iter) )
931  {
932  expression e = EXPRESSION(CAR(iter));
934  if(expression_constant_p(e) || formal_p)
935  {
936  /* no support for array inital value in fortran */
938  {
942  make_reference(scalar_holder,CONS(EXPRESSION,int_to_expression(index),NIL))
943  ),
945  }
946  else
947  {
948  inits=CONS(EXPRESSION,copy_expression(e),inits);
949  }
950  if(formal_p)
951  {
952  entity current_scalar = expression_to_entity(e);
953  expression replacement = make_entity_expression(scalar_holder,make_expression_list(int_to_expression(index)));
954  replacements=gen_cons(current_scalar,gen_cons(replacement,replacements));
955  }
956  else
957  {
958  expression replacement = make_entity_expression(scalar_holder,make_expression_list(int_to_expression(index)));
959  *REFCAR(iter) = (gen_chunkp)replacement;
960  }
961  }
962  else
963  {
964  entity current_scalar = expression_to_entity(e);
965  inits=CONS(EXPRESSION,int_to_expression(0),inits);
966  expression replacement = make_entity_expression(scalar_holder,make_expression_list(int_to_expression(index)));
967  replacements=gen_cons(current_scalar,gen_cons(replacement,replacements));
968  }
969  index++;
970  }
971  /* manage replacements in the end, otherwise it disturbs the whole process */
972  replacements=gen_nreverse(replacements);
973  for(list iter = replacements;!ENDP(iter);POP(iter))
974  {
975  expression r = EXPRESSION(CAR(iter));
976  POP(iter);
977  entity e = ENTITY(CAR(iter));
980  }
981  gen_free_list(replacements);
983  {
984  free_value(entity_initial(scalar_holder));
985  entity_initial(scalar_holder) = make_value_expression(
988  gen_nreverse(inits)
989  )
990  )
991  );
992  }
993  else if(!ENDP(new_statements))
995  argsType=CONSEC_REFS;
996  fstExp = EXPRESSION(CAR(CDR(args)));
997 
998  }
999  if(all_same_aligned_ref)
1000  {
1001  argsType=CONSEC_REFS;
1002  }
1003 
1004 
1005 
1006  /* Now that the analyze is done, we can generate an "optimized"
1007  * load instruction.
1008  */
1009  list current_args = NIL;
1010  char* tofree = NULL;
1011  switch(argsType)
1012  {
1013  case CONSEC_REFS:
1014  case MASKED_CONSEC_REFS:
1015  {
1016 
1017  if (loadstore_type_conversion_string(argc, args, &lsType, isLoad))
1018  tofree=lsType;
1019 
1020  if(get_bool_property("SIMD_FORTRAN_MEM_ORGANISATION"))
1021  {
1022  current_args = make_expression_list(
1023  copy_expression(EXPRESSION(CAR(args))),
1024  copy_expression(fstExp));
1025  }
1026  else
1027  {
1028  expression addr = fstExp;
1029  current_args = make_expression_list( copy_expression(EXPRESSION(CAR(args))), copy_expression(addr));
1030  }
1031 
1032  gSimdCost += - argc + 1;
1033 
1034  break;
1035  }
1036 
1037  case CONSTANT:
1038  {
1039  gSimdCost += - argc + 1;
1040 
1041  break;
1042  }
1043 
1044  case OTHER:
1045  {
1046  if (loadstore_type_conversion_string(argc, args, &lsType, isLoad))
1047  tofree=lsType;
1048  current_args=gen_full_copy_list(args);
1049  } break;
1050  case BROADCAST:
1051  current_args = make_expression_list(
1052  copy_expression(EXPRESSION(CAR(args))),
1053  copy_expression(fstExp)
1054  );
1055  default:
1056  break;
1057  }
1058  /* make the new binding available to everybody */
1060 
1061  asprintf(&functionName, "%s%s", funcNames[argsType][isLoad], lsType);
1062  if(tofree) free(tofree);
1063  statement es = make_exec_statement_from_name(functionName, current_args);
1064  free(functionName);
1065  return es;
1066 
1067 }
1068 statement make_shuffle_statement(entity *from,list expressions,int *perms) {
1069  list shuffle=NIL;
1070  FOREACH(EXPRESSION,_,expressions)
1073  entity out = make_entity_copy(*from);
1075  string sshuffle;
1076  statement outs;
1077  /* If the permutation indexes are equivalent to an invertion,
1078  * generate an SIMD_INVERT function (useful for some MIS). */
1079  if (perms[0] == 4 && perms[1] == 3 && perms[2] == 2 && perms[3] == 1) {
1080  asprintf(&sshuffle,"SIMD_INVERT_%s",
1081  get_vect_name_from_data(gen_length(expressions),expressions));
1082  list args = NIL;
1083  args = CONS(EXPRESSION,entity_to_expression(*from),args);
1084  args = CONS(EXPRESSION,entity_to_expression(out),args);
1085 
1086  outs = instruction_to_statement(
1088  make_call(
1090  args)
1091  )
1092  );
1093  }
1094  else {
1095  asprintf(&sshuffle,"SIMD_SHUFFLE_%s",
1096  get_vect_name_from_data(gen_length(expressions),expressions));
1097 
1098  outs = instruction_to_statement(
1100  make_call(
1104  )
1105  );
1106  }
1107  *from=out;
1108  return outs;
1109 }
1110 
1111 
1112 static statement make_load_statement(int argc, list args)
1113 {
1114  return make_loadsave_statement(argc, args, true);
1115 }
1116 
1117 static statement make_save_statement(int argc, list args)
1118 {
1119  return make_loadsave_statement(argc, args, false);
1120 }
1121 
1122 
1123 
1124 
1125 
1126 
1127 
1129 {
1130  simdstatement ss;
1131  size_t nbargs;
1132 
1133  /* find out the number of arguments needed */
1134  nbargs = opcodeClass_nbArgs(kind);
1135 
1136  /* allocate memory */
1137  ss = make_simdstatement(oc,
1138  nbargs,
1139  (entity *)malloc(sizeof(entity)*nbargs),
1140  (expression*)malloc(sizeof(expression) * nbargs * opcode_vectorSize(oc)));
1141 
1142 
1143  /* create the simd vector entities */
1145  int j=nbargs-1;
1146  pips_assert("nb parameters match nb dummy parameters",nbargs==gen_length(*args));
1147  FOREACH(EXPRESSION,exp,*args)
1148  {
1149  enum basic_utype basicTag = get_basic_from_opcode(oc, nbargs-1-j);
1151  register void * hiter = NULL;
1152  expression key;
1153  entity value;
1154  while ((hiter = hash_table_scan(expression_to_entity, hiter, (void**)&key, (void**)&value))) {
1155  if( expression_equal_p(exp,key ) ) {
1156  simdstatement_vectors(ss)[j] = value;
1157  break;
1158  }
1159  }
1160 
1162  {
1163  simdstatement_vectors(ss)[j] =
1165  opcode_vectorSize(oc),
1166  basicTag);
1168  }
1169  j--;
1170  }
1172 
1173  /* Fill the matrix of arguments */
1174  for(int j=0; j<opcode_vectorSize(oc); j++)
1175  {
1176 
1177  list l = args[j];
1178 
1179  for(int i=nbargs-1; i>=0; i--)
1180  {
1181  expression e = EXPRESSION(CAR(l));
1182 
1183  //Store it in the argument's matrix
1184  simdstatement_arguments(ss)[j + opcode_vectorSize(oc) * i] = e;
1185 
1186  l = CDR(l);
1187  }
1188  }
1189 
1190  return ss;
1191 }
1192 
1194 {
1195  list args[MAX_PACK];
1196  /* there should be a better order than this */
1197  list first = statements;
1198  list last = gen_last(first);
1199  list kinds = set_to_list(opkinds);
1200 
1201  pips_debug(3,"make_simd_statements 1\n");
1202 
1203  if (first == last)
1204  return simdstatement_undefined;
1205 
1206  pips_debug(3,"make_simd_statements 2\n");
1207 
1208  list i = first;
1210 
1211  opcodeClass type = OPCODECLASS(CAR(kinds));
1212  {
1213  int index;
1214  opcode oc;
1215  list j;
1216 
1217  /* get the variables */
1218  for( index = 0, j = i;
1219  (index < MAX_PACK) && (j != CDR(last));
1220  index++, j = CDR(j) )
1221  {
1223  args[index] = match_args(m);
1224  }
1225 
1226  /* compute the opcode to use */
1227  oc = get_optimal_opcode(type, index, args);
1228 
1229  if (!opcode_undefined_p(oc))
1230  {
1231  /* update the pointer to the next statement to be processed */
1232  for(index = 0;
1233  (index<opcode_vectorSize(oc)) && (i!=CDR(last));
1234  index++)
1235  {
1236  i = CDR(i);
1237  }
1238 
1239  /* generate the statement information */
1240  pips_debug(3,"make_simd_statements : simd\n");
1241  instr = make_simd_statement(type, oc, args);
1242  }
1243  }
1244 
1245  pips_debug(3,"make_simd_statements 3\n");
1246  return instr;
1247 }
1248 
1250 {
1251  list args = NIL;
1252  int i;
1253 
1254  for(i = 0; i < simdstatement_nbArgs(ss); i++)
1255  {
1256  args = CONS(EXPRESSION,
1258  args);
1259  }
1260 
1262 
1264 }
1265 
1266 static
1268 {
1269  list args = NIL;
1271  {
1272  //Build the arguments list
1273  for(int i = opcode_vectorSize(simdstatement_opcode(si))-1;
1274  i >= 0;
1275  i--)
1276  {
1277  args = CONS(EXPRESSION,
1279  args);
1280  }
1283  if(!entity_undefined_p(vector)){
1285  return shuffle;
1286  }
1287  else {
1288  args = CONS(EXPRESSION,
1290  args);
1291 
1292  //Make a load statement
1293  return make_load_statement(
1295  args);
1296  }
1297  }
1298 }
1299 
1301 {
1302  list args = NIL;
1303  int i;
1305  (simdstatement_nbArgs(si)-1);
1306 
1307  for(i = opcode_vectorSize(simdstatement_opcode(si))-1;
1308  i >= 0;
1309  i--)
1310  {
1311  args = CONS(EXPRESSION,
1312  (
1313  simdstatement_arguments(si)[i + offset]),
1314  args);
1315  }
1316 
1317  args = CONS(EXPRESSION,
1319  args);
1320 
1322 }
1323 
1324 
1325 list generate_simd_code(simdstatement ssi, float * simdCost)
1326 {
1327  gSimdCost = 0;
1328 
1329  pips_debug(3,"generate_simd_code 1\n");
1330 
1331  /* this is the classical generation process:
1332  * several load, an exec and a store
1333  */
1334  //First, the load statement(s)
1335  list loads=NIL;
1336  for(int i = 0; i < simdstatement_nbArgs(ssi)-1; i++)
1337  {
1338  statement s = generate_load_statement(ssi, i);
1339  if (! statement_undefined_p(s))
1340  loads = CONS(STATEMENT, s, loads);
1341  }
1342 
1343  //Then, the exec statement
1345 
1346  //Finally, the save statement (always generated. It is up to
1347  //latter phases (USE-DEF elimination....) to remove it, if needed
1349 
1350  list out = NIL;
1351  out=CONS(STATEMENT,save,CONS(STATEMENT,exec,loads));
1352  *simdCost += gSimdCost;
1353  pips_debug(3,"generate_simd_code 2 that costs %lf\n",gSimdCost);
1354  /* the order is reversed, but we use it */
1355  return out;
1356 }
int get_int_property(const string)
call make_call(entity a1, list a2)
Definition: ri.c:269
basic make_basic_typedef(entity _field_)
Definition: ri.c:185
value make_value_unknown(void)
Definition: ri.c:2847
value make_value_expression(expression _field_)
Definition: ri.c:2850
syntax make_syntax_call(call _field_)
Definition: ri.c:2500
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
type make_type_variable(variable _field_)
Definition: ri.c:2715
storage make_storage_rom(void)
Definition: ri.c:2285
syntax make_syntax_sizeofexpression(sizeofexpression _field_)
Definition: ri.c:2506
type copy_type(type p)
TYPE.
Definition: ri.c:2655
void free_reference(reference p)
Definition: ri.c:2050
basic make_basic_int(intptr_t _field_)
Definition: ri.c:158
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
basic make_basic_float(intptr_t _field_)
Definition: ri.c:161
dimension make_dimension(expression a1, expression a2, list a3)
Definition: ri.c:565
sizeofexpression make_sizeofexpression_type(type _field_)
Definition: ri.c:2177
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
instruction make_instruction_call(call _field_)
Definition: ri.c:1184
value copy_value(value p)
VALUE.
Definition: ri.c:2784
bool expression_consistent_p(expression p)
Definition: ri.c:859
void free_expression(expression p)
Definition: ri.c:853
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
void free_basic(basic p)
Definition: ri.c:107
bool entity_consistent_p(entity p)
Definition: ri.c:2530
void free_value(value p)
Definition: ri.c:2787
simdstatement make_simdstatement(opcode a1, intptr_t a2, entity *a3, expression *a4)
Definition: sac_private.c:418
opcode make_opcode(string a1, intptr_t a2, list a3, float a4)
Definition: sac_private.c:195
@ DC_REF_TOK
SC_REF_TOK
Definition: patterns.h:66
@ SC_REF_TOK
DF_REF_TOK
Definition: patterns.h:65
@ HI_REF_TOK
QI_REF_TOK
Definition: patterns.h:60
@ DI_REF_TOK
SI_REF_TOK
Definition: patterns.h:62
@ SI_REF_TOK
HI_REF_TOK
Definition: patterns.h:61
@ QI_REF_TOK
REFERENCE_TOK
Definition: patterns.h:59
@ SF_REF_TOK
DI_REF_TOK
Definition: patterns.h:63
@ DF_REF_TOK
SF_REF_TOK
Definition: patterns.h:64
static int count
Definition: SDG.c:519
static FILE * out
Definition: alias_check.c:128
static entity mod_ent
@ INT
Definition: atomic.c:48
static int num
Definition: bourdoncle.c:137
static Value offset
Definition: translation.c:283
list load_proper_rw_effects_list(statement)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#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
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....
union gen_chunk * gen_chunkp
void gen_full_free_list(list l)
Definition: genClib.c:1023
void * malloc(YYSIZE_T)
void free(void *)
bool references_may_conflict_p(reference r1, reference r2)
Check if two references may conflict.
Definition: conflicts.c:426
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
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void replace_entity(void *s, entity old, entity new)
per variable version of replace_entities.
Definition: replace.c:113
void replace_entity_by_expression(void *s, entity ent, expression exp)
replace all reference to entity ent by expression exp in s.
Definition: replace.c:220
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
#define REFCAR(pc)
Get the adress of the first element of a list.
Definition: newgen_list.h:119
#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
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
#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
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
#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
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
bool gen_equals(const list l0, const list l1, gen_eq_func_t equals)
compares two lists using the functor given in parameters returns true if for all n,...
Definition: list.c:192
statement make_assign_statement(expression, expression)
Definition: statement.c:583
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
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
void * hash_table_scan(hash_table htp, void *hentryp_arg, void **pkey, void **pval)
Definition: hash.c:844
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#define BROADCAST
#define new_statements(p)
Definition: inlining.c:97
float_t save[SIZE][SIZE]
Definition: jacobi.c:9
#define _
A substitute for POSIX 2008 <stddef.h>, for platforms that have issues.
Definition: stddef.in.h:59
#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 same_stringn_p(a, b, c)
Definition: misc-local.h:199
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
#define assert(ex)
Definition: newgen_assert.h:41
string strlower(string, const char *)
Definition: string.c:228
string strupper(string, const char *)
Definition: string.c:213
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
@ hash_pointer
Definition: newgen_hash.h:32
#define hash_put_or_update(h, k, v)
Definition: newgen_hash.h:80
#define HASH_FOREACH(key_type, k, value_type, v, ht)
Definition: newgen_hash.h:71
#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 same_string_p(s1, s2)
list set_to_list(const set)
create a list from a set the set is not freed
Definition: set.c:436
bool(* gen_eq_func_t)(const void *, const void *)
Definition: newgen_types.h:115
string expression_to_string(expression e)
Definition: expression.c:77
void set_bool_property(const char *, bool)
static const char * prefix
#define make_expression_list(stats...)
#define binary_call_rhs(c)
#define MINUS_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define NORMALIZE_EXPRESSION(e)
#define expression_scalar_p(e)
#define call_to_statement(c)
#define ADDRESS_OF_OPERATOR_NAME
#define binary_call_lhs(c)
#define BRACE_INTRINSIC
Definition: ri-util-local.h:85
#define MULTIPLY_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
entity FindEntity(const char *package, const char *name)
Retrieve an entity from its package/module name and its local name.
Definition: entity.c:1503
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
entity entity_field_to_entity_struct(entity f)
Definition: entity.c:905
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
bool c_module_p(entity m)
Test if a module "m" is written in C.
Definition: entity.c:2777
bool same_struct_entity_p(const entity e0, const entity e1)
Definition: entity.c:1012
entity make_entity_copy(entity e)
Create a copy of an entity, with (almost) identical type, storage and initial value if move_initializ...
Definition: entity.c:2433
bool entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857
bool fortran_module_p(entity m)
Test if a module is in Fortran.
Definition: entity.c:2799
entity module_name_to_runtime_entity(const char *name)
similar to module_name_to_entity but generates a warning and a stub if the entity is not found
Definition: entity.c:1485
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
expression reference_to_expression(reference r)
Definition: expression.c:196
expression make_entity_expression(entity e, cons *inds)
Definition: expression.c:176
bool simplify_expression(expression *pexp)
use polynomials to simplify an expression in some cases this operation can change the basic of the ex...
Definition: expression.c:3770
bool expression_field_p(expression e)
The expression is of kind "s.a", where "s" is a struct and a "a" field.
Definition: expression.c:491
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
expression make_op_exp(char *op_name, expression exp1, expression exp2)
================================================================
Definition: expression.c:2012
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
expression reference_offset(reference ref)
computes the offset of a C reference with its origin
Definition: expression.c:3807
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
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
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
type ultimate_type(type)
Definition: type.c:3466
int basic_type_size(basic)
See also SizeOfElements()
Definition: type.c:1074
void AddLocalEntityToDeclarations(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:233
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
int dimension_size(dimension)
this function computes the size of a dimension.
Definition: size.c:491
void AddEntityToCurrentModule(entity)
Add a variable entity to the current module declarations.
Definition: variable.c:260
bool formal_parameter_p(entity)
Definition: variable.c:1489
_int SizeOfElements(basic)
This function returns the length in bytes of the Fortran or C type represented by a basic,...
Definition: size.c:297
entity make_new_scalar_variable_with_prefix(const char *, entity, basic)
Create a new scalar variable of type b in the given module.
Definition: variable.c:592
basic basic_of_expressions(list, bool)
Definition: type.c:2040
basic basic_of_reference(reference)
Retrieves the basic of a reference in a newly allocated basic object.
Definition: type.c:1459
basic_utype
Definition: ri.h:570
@ is_basic_float
Definition: ri.h:572
@ is_basic_int
Definition: ri.h:571
@ is_basic_logical
Definition: ri.h:573
@ is_basic_complex
Definition: ri.h:575
#define type_struct(x)
Definition: ri.h:2964
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference_p(x)
Definition: ri.h:2728
struct _newgen_struct_value_ * value
Definition: ri.h:455
#define syntax_reference(x)
Definition: ri.h:2730
#define reference_variable(x)
Definition: ri.h:2326
#define basic_typedef_p(x)
Definition: ri.h:641
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define basic_tag(x)
Definition: ri.h:613
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define basic_overloaded_p(x)
Definition: ri.h:623
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define basic_typedef(x)
Definition: ri.h:643
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define CONSTANT(x)
CONSTANT.
Definition: ri.h:796
#define reference_indices(x)
Definition: ri.h:2328
#define expression_undefined_p(x)
Definition: ri.h:1224
#define variable_dimensions(x)
Definition: ri.h:3122
#define syntax_undefined
Definition: ri.h:2676
#define statement_undefined_p(x)
Definition: ri.h:2420
#define entity_type(x)
Definition: ri.h:2792
#define expression_syntax(x)
Definition: ri.h:1247
#define type_variable_p(x)
Definition: ri.h:2947
#define variable_basic(x)
Definition: ri.h:3120
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
#define SIMD_BROADCAST_SUFFIX
Definition: sac-local.h:55
#define SIMD_GENERIC_SUFFIX
Definition: sac-local.h:53
#define SIMD_MASKED_SUFFIX
simd_loop_const_elim.c
Definition: sac-local.h:52
#define SIMD_CONSTANT_SUFFIX
Definition: sac-local.h:54
simdstatement make_simd_statements(set opkinds, list statements)
Definition: codegen.c:1193
statement make_shuffle_statement(entity *from, list expressions, int *perms)
Definition: codegen.c:1068
static bool simd_vector_expression_p(expression e)
expression is an simd vector if it is a reference array containing VECTOR_POSTFIX in its name
Definition: codegen.c:210
static basic get_typedefed_array(const char *type_name, basic b, list dims)
Definition: codegen.c:629
static statement make_loadsave_statement(int argc, list args, bool isLoad)
Definition: codegen.c:795
static entity make_new_simd_vector_with_prefix(int itemSize, int nbItems, enum basic_utype basicTag, const char *vname)
Definition: codegen.c:663
static expression offset_of_struct(entity e)
Definition: codegen.c:386
static entity expressions_to_vector(list expressions, statement *shuffle)
Definition: codegen.c:146
list generate_simd_code(simdstatement ssi, float *simdCost)
Definition: codegen.c:1325
opcode generate_opcode(string name, list types, float cost)
auto-guess vector size
Definition: codegen.c:276
#define SAC_ALIGNED_VECTOR_NAME
Definition: codegen.c:645
static entity do_expressions_to_vector(list expressions)
Definition: codegen.c:71
static string get_vect_name_from_data(int argc, list exps)
Definition: codegen.c:524
bool expression_reference_or_field_p(expression e)
Definition: codegen.c:192
static enum basic_utype get_basic_from_opcode(opcode oc, int argNum)
Definition: codegen.c:221
static bool sac_aligned_expression_p(expression e)
Definition: codegen.c:651
static void make_permutations_indexes(list exp_final, list exp_loaded, int *perms)
This function will create the permutations indexes that will allow the creation of exp_final from exp...
Definition: codegen.c:105
static hash_table vector_to_expressions
Definition: codegen.c:58
static simdstatement make_simd_statement(opcodeClass kind, opcode oc, list *args)
Definition: codegen.c:1128
static expression sreference_offset(reference r)
computes the offset between an entity and its reference
Definition: codegen.c:373
static bool consecutive_expression_p(expression e0, int lastOffset, expression e1)
Definition: codegen.c:463
static void replace_subscript(expression e)
Definition: codegen.c:580
static statement generate_load_statement(simdstatement si, int line)
Definition: codegen.c:1267
bool simd_vector_entity_p(entity e)
Definition: codegen.c:197
bool sac_aligned_entity_p(entity e)
Definition: codegen.c:646
static void update_vector_to_expressions(entity e, list exps)
Definition: codegen.c:83
static float gSimdCost
Definition: codegen.c:56
static statement generate_exec_statement(simdstatement ss)
Definition: codegen.c:1249
static opcode get_optimal_opcode(opcodeClass kind, int argc, list *args)
Computes the optimal opcode for simdizing 'argc' statements of the 'kind' operation,...
Definition: codegen.c:297
static statement make_exec_statement_from_opcode(opcode oc, list args)
Definition: codegen.c:624
static statement generate_save_statement(simdstatement si)
Definition: codegen.c:1300
void init_vector_to_expressions()
codegen.c
Definition: codegen.c:59
static statement make_save_statement(int argc, list args)
Definition: codegen.c:1117
void invalidate_expressions_in_statement(statement s)
Definition: codegen.c:162
#define MAX_PACK
Definition: codegen.c:52
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
static statement make_exec_statement_from_name(string ename, list args)
Definition: codegen.c:602
static entity try_all_permutations(list expressions, list remainder, list exp_org, statement *shuffle, int *perms)
Definition: codegen.c:121
static bool loadstore_type_conversion_string(int argc, list args, string *lsType, bool isLoad)
This function change the "load/store type" to XX_TO_XX if a conversion is needed.
Definition: codegen.c:742
int get_subwordSize_from_opcode(opcode oc, int argNum)
Definition: codegen.c:246
#define VECTOR_POSTFIX
Definition: codegen.c:53
static expression distance_between_entity(const entity e0, const entity e1)
Definition: codegen.c:404
static string get_simd_vector_type(list lExp)
Definition: codegen.c:494
static entity make_new_simd_vector(int itemSize, int nbItems, enum basic_utype basicTag)
Definition: codegen.c:734
static statement make_load_statement(int argc, list args)
Definition: codegen.c:1112
statement sac_current_block
Definition: simdizer.c:722
match get_statement_match_of_kind(statement, opcodeClass)
simdizer.c
Definition: simdizer.c:101
instruction sac_real_current_instruction
Definition: simdizer.c:723
#define opcodeClass_nbArgs(x)
Definition: sac_private.h:536
#define simdstatement_undefined
Definition: sac_private.h:465
#define match_args(x)
Definition: sac_private.h:253
#define opcode_vectorSize(x)
Definition: sac_private.h:291
#define simdstatement_nbArgs(x)
Definition: sac_private.h:493
#define simdstatement_opcode(x)
Definition: sac_private.h:491
#define opcode_undefined_p(x)
Definition: sac_private.h:264
#define opcode_name(x)
Definition: sac_private.h:289
#define opcode_undefined
Definition: sac_private.h:263
#define opcodeClass_opcodes(x)
Definition: sac_private.h:538
#define simdstatement_vectors(x)
Definition: sac_private.h:495
#define opcode_cost(x)
Definition: sac_private.h:295
#define OPCODECLASS(x)
OPCODECLASS.
Definition: sac_private.h:501
#define opcode_argType(x)
Definition: sac_private.h:293
#define OPCODE(x)
OPCODE.
Definition: sac_private.h:257
#define simdstatement_arguments(x)
Definition: sac_private.h:497
char * strdup()
static int line
FLEX_SCANNER.
Definition: scanner.c:852
void shuffle(int n, float r[n], float r3[n], float r2[n], float a[n], float b[n])
Definition: shuffle.c:9
#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
test de chernikovaa
struct vector vector
test de chernikovaa
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
#define remainder
Definition: vasnprintf.c:209