PIPS
atomizer.c
Go to the documentation of this file.
1 /*
2 
3  $Id: atomizer.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 /* An atomizer that uses the one made by Fabien Coelho for HPFC,
28  * and is in fact just a hacked version of the one made by Ronan
29  * Keryell...
30  */
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 
36 #include "genC.h"
37 #include "linear.h"
38 #include "ri.h"
39 #include "effects.h"
40 
41 #include "ri-util.h"
42 #include "effects-util.h"
43 #include "text-util.h"
44 #include "database.h"
45 #include "misc.h"
46 #include "pipsdbm.h"
47 #include "resources.h"
48 #include "control.h"
49 #include "arithmetique.h"
50 #include "reductions.h"
51 
52 #include "effects-generic.h"
53 #include "effects-simple.h"
54 #include "properties.h"
55 
56 #include "sac.h"
57 
59 
60 
61 static
62 void patch_constant_size(syntax s, bool* patch_all)
63 {
64  switch(syntax_tag(s))
65  {
66  case is_syntax_call:
67  {
68  call c = syntax_call(s);
70  {
73  basic_int(b)= 1;
74  }
75  } break;
77  *patch_all = false;
78  break;
79  default:
80  break;
81  };
82 }
84 
85 /* returns the assignment statement if moved, or NULL if not.
86  */
88  expression e)
89 {
90  basic bofe = basic_undefined;
91 
92  /* it does not make sense to atomize a range...
93  */
94  if (syntax_range_p(expression_syntax(e))) return NULL;
95 
96  /* SG: in case of expression similar to (a+2), if a is a short (or a char ...),
97  * the user may expect the result is a short too
98  * the C syntax expect 2 is an int
99  * set the property to false if you want to override this behavior
100  */
101  if( get_bool_property("SIMD_OVERRIDE_CONSTANT_TYPE_INFERENCE") )
102  {
103  expression etemp = copy_expression(e);
104  bool patch_all=true;
105  /* force all integer to char, then compute the basic
106  * validate only if we can guess the size from something not a constant integer
107  */
109  if( !patch_all )
110  bofe=basic_of_expression(etemp);
111  free_expression(etemp);
112  }
113 
114  if(basic_undefined_p(bofe) )
115  bofe = basic_of_expression(e);
116 
117  if(!basic_undefined_p(bofe)) {
118  if (!basic_overloaded_p(bofe))
119  {
120  entity newvar = (*create)(get_current_module_entity(), bofe);
121  AddEntityToCurrentModule(newvar);
126 
127  return assign;
128  }
129 
130  free_basic(bofe);
131  }
132  return NULL;
133 }
134 
135 
136 /* This function computes the maximum width of all the variables used in a call
137  */
138 static void get_type_max_width(call ca, int* maxWidth)
139 {
141  {
142  syntax s = expression_syntax(arg);
143 
144  switch(syntax_tag(s))
145  {
146  case is_syntax_call:
147  {
148  call c = syntax_call(s);
149 
150  entity op = call_function(c);
151  if ( ENTITY_FIELD_P(op) || ENTITY_POINT_TO_P(op))
152  {
154  *maxWidth=MAX(*maxWidth , basic_type_size(bas));
155  free_basic(bas);
156  }
157  else if (!call_constant_p(c))
158  get_type_max_width(c, maxWidth);
159  } break;
160 
161  case is_syntax_reference:
162  {
164  *maxWidth=MAX(*maxWidth , basic_type_size(bas));
165  free_basic(bas);
166  } break;
167  case is_syntax_subscript:
168  {
170  *maxWidth=MAX(*maxWidth , basic_type_size(bas));
171  free_basic(bas);
172  } break;
173  case is_syntax_cast:
174  {
175  cast ca = syntax_cast(s);
176  type t = cast_type(ca);
177  *maxWidth=MAX(*maxWidth ,type_memory_size(t));
178  } break;
180  *maxWidth=MAX(*maxWidth ,DEFAULT_INTEGER_TYPE_SIZE);
181  break;
182 
183  default:pips_internal_error("syntax_tag %u not supported yet",syntax_tag(s));
184 
185  }
186  }
187 
188 }
189 
190 /* This function aims at changing the basic size of the left expression of
191  * the newly created assign statement
192  */
194 {
196  {
197  int maxWidth = -1;
200 
201  // Check that the right expression is a call statement
202  if(expression_call_p(rExp))
203  {
204 
205  // Check that the statement can be potentially integrated in a
206  // SIMD statement
207  // SG: atomizer is no longer limited to sac
208  // if(match_statement(stat) != NIL)
209  {
211  }
212 
213  // If the maxWidth of the right expression is smaller than the width
214  // of the current left expression, then replace the left expression width
215  // by maxWidth
216  if(maxWidth > 0)
217  {
218  basic lExpBasic = expression_basic(lExp);
219  maxWidth=MIN(maxWidth,basic_type_size(lExpBasic));
220  }
221  }
222  }
223 }
224 
225 /* This function insert stat before orginal_statement in the code
226  */
228 {
230  // If cs is already a sequence, we just need to insert stat in cs
232  {
236  }
237  // If cs is not a sequence, we have to create one sequence composed of
238  // cs then orginal_statement
239  else
240  {
241  statement_label(stat) = statement_label(cs);
242 
244  statement_number(cs),
245  statement_ordering(cs),
246  statement_comments(cs),
249  NULL,
251 
254  CONS(STATEMENT,
256  NIL)));
257 
263  }
264 }
265 
266 static
268 {
271  return e;
272 }
273 
274 static
276 {
277  syntax s = expression_syntax(ce);
279 
280  // Atomize expression only if this is a call expression
281  if(syntax_call_p(s))
282  {
283  call cc = syntax_call(s);
284 
285  // Atomize expression only if the call is not a constant
286  if(FUNC_TO_ATOMIZE_P(cc))
287  {
288  /* If the current call is not an assign call,
289  * let's atomize the current argument
290  * sg: also try to be smart and make reduction appear if any
291  */
292 
294  simd_insert_statement(cs, stat);
295  }
296  }
297 }
299 {
300  if( expression_reference_p(exp) ) {
301  if( get_bool_property("SIMD_ATOMIZER_ATOMIZE_REFERENCE") ) return true;
302  else {
306  if(expression_linear_p(ind))
307  gen_recurse_stop(ind);
308  }
309  }
310  }
312  {
313  call c = expression_call(exp);
314  entity op = call_function(c);
315  return !ENTITY_POINT_TO_P(op) && !ENTITY_FIELD_P(op);
316  }
317  return true;
318 }
319 
320 /* This function is called for each call statement and atomize it
321 */
323 {
325 
326  // Initialize orginal_statement if this is the first argument
328 
329  // For each call argument, the argument is atomized if needed
331  {
333  expression rhs = binary_call_rhs(c);
334  if( expression_call_p(rhs) )
335  {
338  }
339  else if (expression_reference_p(rhs)) {
341  }
342  if(get_bool_property("SIMD_ATOMIZER_ATOMIZE_LHS"))
343  {
346  }
347  }
348 }
349 
350 /* This function is called for all statements in the code
351 */
353 {
354  // Only a call statement can be atomized
356  {
358  }
359 }
360 
361 bool simd_atomizer(char * mod_name)
362 {
363  /* get the resources */
364  statement mod_stmt = (statement)
365  db_get_memory_resource(DBR_CODE, mod_name, true);
366 
369 
370  debug_on("SIMD_ATOMIZER_DEBUG_LEVEL");
371 
372 
373  /* Now do the job */
375 
376  /* Reorder the module, because new statements have been added */
377  module_reorder(mod_stmt);
378  DB_PUT_MEMORY_RESOURCE(DBR_CODE, mod_name, mod_stmt);
379 
380  /* update/release resources */
383 
384  debug_off();
385 
386  return true;
387 }
388 
390  reference redref = reduction_reference(r);
392 
393  if(expression_call_p(e)) {
394  call ce = expression_call(e);
395  if(same_entity_p(call_function(ce), redop)) {
396  expression lhs = binary_call_lhs(ce),
397  rhs = binary_call_rhs(ce);
398 
399  do_expression_reduction(s, r, lhs);
400  do_expression_reduction(s, r, rhs);
401 
402  if(expression_reference_p(lhs) &&
403  reference_equal_p(expression_reference(lhs), redref)) {
405  }
406  else if(expression_reference_p(rhs) &&
407  reference_equal_p(expression_reference(rhs), redref)) {
409  }
410  else
411  {
414  MakeBinaryCall(redop,
416  copy_expression(rhs)));
419  insert_statement(s, snew, false);
421  }
422  return true;
423  }
424  }
425  return false;
426 }
427 
428 
431  if(!ENDP(reductions)) {
433  /* the reduction must be of the pattern red = red op exp1 op exp2 */
434  reference redref = reduction_reference(r);
436  if(statement_call_p(s)) {
437  call c = statement_call(s);
438  entity assign = call_function(c);
439  if(ENTITY_ASSIGN_P(assign)) {
440  expression lhs = binary_call_lhs(c);
441  if(expression_reference_p(lhs)) {
442  reference rlhs = expression_reference(lhs);
443  if(reference_equal_p(rlhs,redref)) {
444  expression rhs = binary_call_rhs(c);
445  if(do_expression_reduction(s, r, rhs))
447  MakeBinaryCall(redop,
449  copy_expression(rhs))));
450  }
451  }
452  }
453  }
454  }
455  }
456  return true;
457 }
458 
459 bool reduction_atomization(const char * module_name) {
460  /* prelude */
464 
465  /* do the job */
469 
470  /* postlude */
474  return true;
475 }
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
reductions copy_reductions(reductions p)
REDUCTIONS.
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
syntax copy_syntax(syntax p)
SYNTAX.
Definition: ri.c:2442
void free_expression(expression p)
Definition: ri.c:853
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
synchronization make_synchronization_none(void)
Definition: ri.c:2424
void free_basic(basic p)
Definition: ri.c:107
syntax make_syntax_reference(reference _field_)
Definition: ri.c:2494
#define MIN(x, y)
minimum and maximum if they are defined somewhere else, they are very likely to be defined the same w...
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define call_constant_p(C)
Definition: flint_check.c:51
#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 reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#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
#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_insert_before(const void *no, const void *o, list l)
Definition: list.c:238
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
list statement_block(statement)
Get the list of block statements of a statement sequence.
Definition: statement.c:1338
call statement_call(statement)
Get the call of a statement.
Definition: statement.c:1406
bool statement_call_p(statement)
Definition: statement.c:364
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
#define debug_on(env)
Definition: misc-local.h:157
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
entity reduction_operator_entity(reduction_operator op)
match a reduction operator against operator entity
Definition: reductions.c:577
void normalize_all_expressions_of(void *obj)
Definition: normalize.c:668
static char * module
Definition: pips.c:74
void create(char *workspace_name, char **filenames)
create a new workspace...
Definition: pypips.c:239
void reset_cumulated_reductions(void)
void set_cumulated_reductions(pstatement_reductions)
reductions load_cumulated_reductions(statement)
void store_cumulated_reductions(statement, reductions)
#define REDUCTION(x)
REDUCTION.
#define reduction_op(x)
#define reduction_reference(x)
#define reductions_list(x)
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 ENTITY_ASSIGN_P(e)
#define DEFAULT_INTEGER_TYPE_SIZE
#define NORMALIZE_EXPRESSION(e)
#define ENTITY_POINT_TO_P(e)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define ENTITY_FIELD_P(e)
C data structure and pointer management.
#define binary_call_lhs(c)
#define instruction_block(i)
#define empty_comments
Empty comments (i.e.
#define entity_constant_p(e)
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
entity entity_empty_label(void)
Definition: entity.c:1105
bool expression_linear_p(expression e)
returns if e is already normalized and linear.
Definition: eval.c:951
expression reference_to_expression(reference r)
Definition: expression.c:196
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
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
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
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
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
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
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
entity make_new_scalar_variable(entity, basic)
Definition: variable.c:741
void AddEntityToCurrentModule(entity)
Add a variable entity to the current module declarations.
Definition: variable.c:260
int type_memory_size(type)
Definition: size.c:248
basic expression_basic(expression)
Definition: type.c:1115
basic basic_of_reference(reference)
Retrieves the basic of a reference in a newly allocated basic object.
Definition: type.c:1459
#define normalized_undefined
Definition: ri.h:1745
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define functional_result(x)
Definition: ri.h:1444
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define basic_int_p(x)
Definition: ri.h:614
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define call_function(x)
Definition: ri.h:709
#define basic_int(x)
Definition: ri.h:616
#define syntax_call_p(x)
Definition: ri.h:2734
#define statement_ordering(x)
Definition: ri.h:2454
#define syntax_cast(x)
Definition: ri.h:2739
#define type_functional(x)
Definition: ri.h:2952
#define type_variable(x)
Definition: ri.h:2949
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
@ is_syntax_cast
Definition: ri.h:2694
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
@ is_syntax_sizeofexpression
Definition: ri.h:2695
@ is_syntax_subscript
Definition: ri.h:2696
#define basic_overloaded_p(x)
Definition: ri.h:623
#define basic_undefined_p(x)
Definition: ri.h:557
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define statement_label(x)
Definition: ri.h:2450
#define basic_undefined
Definition: ri.h:556
#define expression_undefined
Definition: ri.h:1223
#define reference_indices(x)
Definition: ri.h:2328
#define statement_extensions(x)
Definition: ri.h:2464
#define syntax_call(x)
Definition: ri.h:2736
#define cast_type(x)
Definition: ri.h:745
#define instruction_call_p(x)
Definition: ri.h:1527
#define subscript_array(x)
Definition: ri.h:2561
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define instruction_call(x)
Definition: ri.h:1529
#define syntax_subscript(x)
Definition: ri.h:2745
#define call_arguments(x)
Definition: ri.h:711
#define syntax_range_p(x)
Definition: ri.h:2731
#define entity_type(x)
Definition: ri.h:2792
#define statement_number(x)
Definition: ri.h:2452
#define expression_syntax(x)
Definition: ri.h:1247
#define variable_basic(x)
Definition: ri.h:3120
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define syntax_domain
newgen_synchronization_domain_defined
Definition: ri.h:402
#define FUNC_TO_ATOMIZE_P(call)
Definition: sac-local.h:34
static void atomize_call_statement(statement cs)
This function is called for each call statement and atomize it.
Definition: atomizer.c:322
static expression current_lhs
Definition: atomizer.c:83
static void get_type_max_width(call ca, int *maxWidth)
This function computes the maximum width of all the variables used in a call.
Definition: atomizer.c:138
static void simd_insert_statement(statement cs, statement stat)
This function insert stat before orginal_statement in the code.
Definition: atomizer.c:227
static void simd_do_atomize(expression ce, statement cs)
Definition: atomizer.c:275
static void change_basic_if_needed(statement stat)
This function aims at changing the basic size of the left expression of the newly created assign stat...
Definition: atomizer.c:193
static void atomize_statements(statement cs)
This function is called for all statements in the code.
Definition: atomizer.c:352
static statement orginal_statement
An atomizer that uses the one made by Fabien Coelho for HPFC, and is in fact just a hacked version of...
Definition: atomizer.c:58
static bool do_expression_reduction(statement s, reduction r, expression e)
Definition: atomizer.c:389
static entity sac_make_new_variable(entity module, basic b)
Definition: atomizer.c:267
static bool do_reduction_atomization(statement s)
Definition: atomizer.c:429
bool reduction_atomization(const char *module_name)
Definition: atomizer.c:459
bool simd_atomizer(char *mod_name)
Definition: atomizer.c:361
statement simd_atomize_this_expression(entity(*create)(entity, basic), expression e)
returns the assignment statement if moved, or NULL if not.
Definition: atomizer.c:87
static void patch_constant_size(syntax s, bool *patch_all)
Definition: atomizer.c:62
static bool reference_filter(expression exp, __attribute__((unused)) statement cs)
Definition: atomizer.c:298
#define MAX(x, y)
Definition: string.c:110
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207