PIPS
strength_reduction.c
Go to the documentation of this file.
1 /*
2 
3  $Id: strength_reduction.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 
25 // do not compiled unless required
26 #include "phases.h"
27 #ifdef BUILDER_STRENGTH_REDUCTION
28 
29 #ifdef HAVE_CONFIG_H
30  #include "pips_config.h"
31 #endif
32 /* package induction_substitution
33  */
34 
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <math.h>
38 
39 #include "genC.h"
40 #include "linear.h"
41 
42 #include "misc.h"
43 #include "pipsdbm.h"
44 #include "properties.h"
45 
46 #include "ri.h"
47 #include "ri-util.h"
48 #include "text-util.h" // dump_text
49 
50 #include "control.h" // clean_up_sequences, module_reorder
51 
52 #include "transformer.h" // used
53 #include "effects.h" // used by semantics.h
54 #include "semantics.h" // used
55 #include "effects-generic.h" // used
56 
57 /* strength reduction context */
58 typedef struct {
59  hash_table entity_to_coeff; ///< mapping between an entity and the value of the involved induction variable
60  hash_table entity_to_entity; ///< mapping between an entity and its strength_reduced value
61  entity index; ///< induction variable
62  expression increment; ///< original loop increment
63  expression init; ///< original loop increment initial value
64  list header_statements; ///< assignments from external to internal var
65  list incr_statements; ///< the internal vars increments
66 } strength_reduction_context_t;
67 
68 /* the big stuff is there
69  * for each candidate expression, we examine its linear field and look for something
70  * link a0.{variable}+a1.TCST+a2.{induction variable}+a3.{other symbolic constant}
71  * we normalize this, and if it's ok, we can transform this into
72  * a0'.{variable}+a1'.TCST+a3'.{other symbolic constant}
73  * and increment by @p ctxt->increment * a2'
74  * a new variable is created for each different increment
75  */
76 static bool do_strength_reduction_gather(expression exp, strength_reduction_context_t *ctxt) {
77  /* ensure the normalized field is filled */
80  /* focus on the linear problem */
81  if(normalized_linear_p(n) && VALUE_ZERO != vect_coeff(ctxt->index,normalized_linear(n)) ) {
82  /* we look for a linear form involving constants and our index */
83  entity other = entity_undefined;
84  for(Pvecteur iter=normalized_linear(n);
85  !VECTEUR_NUL_P(iter);iter=vecteur_succ(iter)) {
86  entity var = (entity)vecteur_var(iter);
87  /* constant terms and the index are ignored */
88  if(term_cst(iter) ||
89  same_entity_p(ctxt->index,var) ||
90  entity_constant_p(var)) {
91  continue;
92  }
93  /* the others are stored, but only one per expression
94  * eg: what to do with a + b +i ?
95  * we also have to pay attention to 2a-6i: this one is ok,
96  * it will lead to 2a; a-=3;
97  * but not 3a-4i
98  */
99  else /*if(entity_undefined_p(other))*/ {
101  vect_normalize(pv);
102  Value v = vect_coeff(var,pv);
103  if(value_one_p(v)&& // prefer pointer over scalars to hold the increment
104  (entity_undefined_p(other)||entity_scalar_p(other)||entity_pointer_p(other)))
105  other= var;
106  //else {other=entity_undefined;};//do not manage this case as of now
107  }
108  /*else {
109  other=entity_undefined;// cannot decide between two not constant entities
110  break;
111  }*/
112  }
113  /* we only take care of scalar variables */
114  if(!entity_undefined_p(other) && (entity_scalar_p(other) || entity_pointer_p(other)) ) {
115  /* look for an entity that olds the same increment as ours */
116  entity already_there = entity_undefined;
117  HASH_FOREACH(entity,e,intptr_t,v,ctxt->entity_to_coeff) {
118  if(((intptr_t)vect_coeff(ctxt->index,normalized_linear(n))==v) &&
119  same_entity_p(other,(entity)hash_get(ctxt->entity_to_entity,e)))
120  {
121  already_there=e;
122  break;
123  }
124  }
126  if(entity_undefined_p(already_there)) {
127  /* create a new induction variable */
130  copy_basic(entity_basic(other))
131  );
132  /* memorize it for further use:
133  * *(a+i)=(*a+1)+1;
134  * should lead to *a0=*a0+1; a0++;
135  * and not *a1=*a1+1; a1++;
136  */
137  Value coeff = vect_coeff(ctxt->index,pv);
138  hash_put(ctxt->entity_to_coeff,already_there,(void*)(intptr_t)coeff);
139  hash_put(ctxt->entity_to_entity,already_there,other);
140  AddEntityToCurrentModule(already_there);
141  /* and fill the header / footer / increment */
142  intptr_t v;
143  ctxt->header_statements=CONS(
144  STATEMENT,
146  entity_to_expression(already_there),
147  expression_integer_value(ctxt->init,&v) && v == 0 ?
148  entity_to_expression(other):
149  make_op_exp(
151  entity_to_expression(other),
152  copy_expression(ctxt->init)
153  )
154  ),
155  ctxt->header_statements);
156  /* compute the value of the new increment */
157  expression new_increment=int_to_expression(coeff>0?coeff:-coeff);
158  ctxt->incr_statements=CONS(
159  STATEMENT,
161  make_call(
164  entity_to_expression(already_there),
166  copy_expression(ctxt->increment),
167  new_increment)
168  )
169  )
170  ),
171  ctxt->incr_statements);
172 
173  }
174  /* either way regenerate the expression from the patched linear field*/
175  vect_erase_var(&pv,ctxt->index);
176  vect_chg_var(&pv,other,already_there);
180  );
182  free_expression(p);
183  return false;
184  }
185  }
186  return true;
187 }
188 
189 /* looks for expression in @p l's body that are linear combination of @p l's index
190  * those expressions are strength reduced
191  */
192 static bool do_strength_reduction_in_loop(loop l) {
193  // parent statement
195  // context
196  strength_reduction_context_t ctxt = {
199  loop_index(l),
202  NIL,NIL
203  };
204  // find all possible & relevant cases and fill the context
205  gen_context_recurse(loop_body(l), &ctxt,
206  expression_domain, do_strength_reduction_gather, gen_null2);
207  // insert prelude and postlude that take care of the assignment to the iterator
208  // plus the increments
210  make_block_statement(ctxt.header_statements),
211  true);
213  make_block_statement(ctxt.incr_statements),
214  false);
215 
216  hash_table_free(ctxt.entity_to_coeff);
217  hash_table_free(ctxt.entity_to_entity);
218  return true;
219 }
220 
221 /* dispatch over all loops */
222 static
223 void do_strength_reduction(
226 {
228  loop_domain, do_strength_reduction_in_loop, gen_null);
229 }
230 
231 /* this phase is the opposite of induction substitution:
232  * it generates induction variables
233  * It is a lame implementation without much smart things in it:
234  * works only for loops, generates a lot of copy ...
235  * But it does the job for the simple case I (SG) need in Terapix
236  *
237  *
238  * after a talk with FI, it appears that transformers should be used
239  * to detect induction variable
240  *
241  * deriving the preconditions with respect to induction variable should
242  * also give insightful informations about the strength reduction pattern
243  *
244  * see paper from Robert Paije
245 */
246 bool strength_reduction(const string module_name) {
247  /* prelude */
250  (statement) db_get_memory_resource(DBR_CODE, module_name, true)
251  );
252  /* To set up the hash table to translate value into value names */
254  db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true)
255  );
256  /* do the job */
257  do_strength_reduction(get_current_module_entity(),get_current_module_statement());
258  // we may have done bad things, such has inserting empty statements
260 
261  /* some declaration statements may have been added */
264 
269  return true;
270 }
271 
272 #endif // BUILDER_STRENGTH_REDUCTION
call make_call(entity a1, list a2)
Definition: ri.c:269
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
void free_expression(expression p)
Definition: ri.c:853
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
static statement module_statement
Definition: alias_check.c:125
#define VALUE_ZERO
#define value_one_p(val)
int Value
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
void set_cumulated_rw_effects(statement_effects)
void reset_cumulated_rw_effects(void)
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
#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
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
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
gen_chunk * gen_get_ancestor(int, const void *)
return the first ancestor object found of the given type.
Definition: genClib.c:3560
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#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
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
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_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
#define _UNUSED_
Definition: misc-local.h:232
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_FOREACH(key_type, k, value_type, v, ht)
Definition: newgen_hash.h:71
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26
static char * module
Definition: pips.c:74
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define make_expression_list(stats...)
#define NORMALIZE_EXPRESSION(e)
#define call_to_statement(c)
#define MINUS_UPDATE_OPERATOR_NAME
#define PLUS_UPDATE_OPERATOR_NAME
#define MULTIPLY_OPERATOR_NAME
#define entity_constant_p(e)
#define PLUS_C_OPERATOR_NAME
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
bool 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
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
bool entity_pointer_p(entity e)
Definition: entity.c:745
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 Pvecteur_to_expression(Pvecteur vect)
AP, sep 25th 95 : some usefull functions moved from static_controlize/utils.c.
Definition: expression.c:1825
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
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 entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
void AddEntityToCurrentModule(entity)
Add a variable entity to the current module declarations.
Definition: variable.c:260
entity make_new_scalar_variable_with_prefix(const char *, entity, basic)
Create a new scalar variable of type b in the given module.
Definition: variable.c:592
#define loop_body(x)
Definition: ri.h:1644
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define normalized_linear_p(x)
Definition: ri.h:1779
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
struct _newgen_struct_entity_to_entity_ * entity_to_entity
Definition: ri.h:135
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define range_increment(x)
Definition: ri.h:2292
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define expression_normalized(x)
Definition: ri.h:1249
#define range_lower(x)
Definition: ri.h:2288
#define syntax_undefined
Definition: ri.h:2676
#define loop_range(x)
Definition: ri.h:1642
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define loop_index(x)
Definition: ri.h:1640
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
void reset_semantic_map(void)
#define intptr_t
Definition: stdint.in.h:294
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
bool strength_reduction(const string)
strength_reduction.c
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
#define vecteur_var(v)
#define vecteur_succ(v)
#define VECTEUR_NUL_P(v)
#define term_cst(varval)
Pbase vect_copy(Pvecteur b)
direct duplication.
Definition: alloc.c:240
void vect_erase_var(Pvecteur *ppv, Variable v)
void vect_erase_var(Pvecteur * ppv, Variable v): projection du vecteur *ppv selon la direction v (i....
Definition: unaires.c:106
Value vect_coeff(Variable var, Pvecteur vect)
Variable vect_coeff(Variable var, Pvecteur vect): coefficient de coordonnee var du vecteur vect —> So...
Definition: unaires.c:228
void vect_chg_var(Pvecteur *ppv, Variable v_old, Variable v_new)
void vect_chg_var(Pvecteur *ppv, Variable v_old, Variable v_new) replace the variable v_old by v_new
Definition: unaires.c:168
void vect_normalize(Pvecteur v)
void vect_normalize(Pvecteur v): division de tous les coefficients de v par leur pgcd; "normalisation...
Definition: unaires.c:59