PIPS
strip_mine.c File Reference
#include <stdio.h>
#include <string.h>
#include "genC.h"
#include "linear.h"
#include "misc.h"
#include "pipsdbm.h"
#include "properties.h"
#include "ri.h"
#include "text.h"
#include "ri-util.h"
#include "prettyprint.h"
#include "text-util.h"
#include "control.h"
#include "conversion.h"
#include "transformations.h"
+ Include dependency graph for strip_mine.c:

Go to the source code of this file.

Functions

statement loop_strip_mine (statement loop_statement, int chunk_size, int chunk_number)
 loop_strip_mine(): More...
 
static statement loop_chunk_size_and_strip_mine (list lls, __attribute__((unused)) bool(*unused)(statement))
 Hmmm... More...
 
bool strip_mine (const string mod_name)
 Top-level function. More...
 

Variables

entity selected_label
 Interface with pipsmake for interactive loop transformations: loop interchange, hyperplane method,... More...
 
char * current_module_name
 

Function Documentation

◆ loop_chunk_size_and_strip_mine()

static statement loop_chunk_size_and_strip_mine ( list  lls,
__attribute__((unused)) bool(*)(statement unused 
)
static

Hmmm...

I am not sure it is a good idea to put the user_request()s here. Did the author want to be able to apply loop_chunk_size_and_strip_mine() several times on different loops with different strip mining parameters?

Get the strip_mining kind from the user

Get the strip_mining factor from the user

Return the statement unchanged:

Definition at line 165 of file strip_mine.c.

166 {
167 
168  string resp;
169  int kind, factor;
170  statement stmt, new_s;
171  int chunk_size = -1;
172  int chunk_number = -1;
173 
174  stmt = STATEMENT(CAR(gen_last(lls)));
175 
176  /* Get the strip_mining kind from the user */
177  kind=get_int_property("STRIP_MINE_KIND");
178  if( kind!=0 && kind!=1 ) {
179  resp = user_request("Type of strip-mining:\n - in fixed-size chunks "
180  "(enter 0)\n - in a fixed number of chunks (enter 1)");
181  if ( empty_string_p(resp) ) {
182  goto cancel;
183  }
184  else {
185  if(sscanf(resp, "%d", &kind)!=1 || (kind!= 0 && kind !=1)) {
186  pips_user_error("strip_mining kind should be either 0 or 1!\n");
187  }
188  }
189  }
190 
191  factor=get_int_property("STRIP_MINE_FACTOR");
192  if(factor<=1) {
193 
194  /* Get the strip_mining factor from the user */
195  resp = user_request("What's the stripe %s?\n"
196  "(choose integer greater or egal to 2): ",
197  kind ? "number" : "size");
198  if ( empty_string_p(resp) ) {
199  goto cancel;
200  }
201  else {
202  if(sscanf(resp, "%d", &factor)!=1 || factor <= 1) {
203  user_error("strip_mine",
204  "stripe size or number should be greater than 2\n");
205  }
206  }
207  }
208 
209  if(kind==0) {
210  chunk_size = factor;
211  chunk_number = -1;
212  }
213  else {
214  chunk_size = -1;
215  chunk_number = factor;
216  }
217 
218  pips_debug(1,"strip mine in %d chunks of size %d \n",
219  chunk_number, chunk_size);
220  new_s = loop_strip_mine(stmt,chunk_size,chunk_number);
221  return(new_s);
222 
223 cancel:
224  user_log("Strip mining has been cancelled.\n");
225 
226  /* Return the statement unchanged: */
227  return stmt;
228 }
int get_int_property(const string)
void user_log(const char *format,...)
Definition: message.c:234
bool empty_string_p(const char *s)
Definition: entity_names.c:239
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define user_error(fn,...)
Definition: misc-local.h:265
#define pips_user_error
Definition: misc-local.h:147
string user_request(const char *,...)
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
statement loop_strip_mine(statement loop_statement, int chunk_size, int chunk_number)
loop_strip_mine():
Definition: strip_mine.c:64
Definition: statement.c:54
static Panel_item cancel
Definition: xv_mchoose.c:44

References cancel, CAR, empty_string_p(), gen_last(), get_int_property(), loop_strip_mine(), pips_debug, pips_user_error, STATEMENT, user_error, user_log(), and user_request().

Referenced by strip_mine().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ loop_strip_mine()

statement loop_strip_mine ( statement  loop_statement,
int  chunk_size,
int  chunk_number 
)

loop_strip_mine():

strip_mine.c

Sharing is (theoretically) avoided when the AST is built

Assumption:

  • a loop body can be a loop (no need for a block with one statement, a loop)

compute the expression for the chunk size

make sure that the outer loop does not use a continue that will end up in the inner loop body

derive a new loop index (FI: only one name :-(

build the inner loop preserving the initial index set

update the outer loop

Parameters
loop_statementoop_statement
chunk_sizehunk_size
chunk_numberhunk_number

Definition at line 64 of file strip_mine.c.

66 {
67  loop l = instruction_loop(statement_instruction(loop_statement));
68  loop new_l = loop_undefined;
74  entity index = loop_index(l);
75  statement b = loop_body(l);
76  entity new_index = entity_undefined;
77 
78  debug(9, "loop_strip_mine", "begin: chunk_size = %d,chunk_number = %d\n",
79  chunk_size, chunk_number);
80  pips_assert("loop_strip_mine", ( chunk_size > 1 && chunk_number == -1 )
81  ||
82  (chunk_size == -1 && chunk_number > 1) );
83 
84  if(loop_increment_value(l) != 1)
85  user_error("loop_strip_mine",
86  "Loop increment has to be one for strip-mining!\n");
87 
88  if(get_debug_level()>=9) {
89  print_statement(loop_statement);
90  pips_assert("loop_strip_mine", statement_consistent_p(loop_statement));
91  }
92 
93  /* compute the expression for the chunk size */
94  if(chunk_size==-1) {
95  expression e_number = int_to_expression(chunk_number);
96 
98  size = make_op_exp(PLUS_OPERATOR_NAME, size, copy_expression(e_number));
99  size = make_op_exp(DIVIDE_OPERATOR_NAME, size, e_number);
101  }
102  else {
103  size = int_to_expression(chunk_size);
104  sizem1 = int_to_expression(chunk_size-1);
105  }
106  ifdebug(9) {
107  pips_debug(8, "size = ");
108  print_expression(size);
109  pips_debug(8, "sizem1 = ");
110  print_expression(sizem1);
111  }
112 
113  /* make sure that the outer loop does not use a continue that will
114  end up in the inner loop body */
116 
117  /* derive a new loop index (FI: only *one* name :-( */
118  new_index = make_new_index_entity(index, "_1");
120 
121  /* build the inner loop preserving the initial index set */
122  expression fst_min_param=MakeBinaryCall(entity_intrinsic("+"),entity_to_expression(new_index),sizem1);
123  expression snd_min_parameter=copy_expression(ub);
124  expression min_exp =
125  MakeBinaryCall(entity_intrinsic(MIN_OPERATOR_NAME),fst_min_param,snd_min_parameter);
126  new_l = make_loop(index,
127  make_range(entity_to_expression(new_index),
128  min_exp,
129  int_to_expression(1)),
130  b,
135  NIL);
136 
138 
139  ifdebug(8) {
140  pips_debug(8, "new inner loop:");
141  print_statement(new_s);
142  pips_assert("loop_strip_mine", statement_consistent_p(new_s));
143  }
144 
145  /* update the outer loop */
146  loop_index(l) = new_index;
148  loop_body(l) = new_s;
149 
150  ifdebug(8) {
151  print_statement(loop_statement);
152  pips_assert("loop_statement consistent_p", statement_consistent_p(loop_statement));
153  }
154 
155  pips_debug(8, "end\n");
156  return(loop_statement);
157 }
execution make_execution(enum execution_utype tag, void *val)
Definition: ri.c:838
loop make_loop(entity a1, range a2, statement a3, entity a4, execution a5, list a6)
Definition: ri.c:1301
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
bool statement_consistent_p(statement p)
Definition: ri.c:2195
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
range make_range(expression a1, expression a2, expression a3)
Definition: ri.c:2041
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
int loop_increment_value(loop l)
Definition: loop.c:714
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
int get_debug_level(void)
GET_DEBUG_LEVEL returns the current debugging level.
Definition: debug.c:67
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
#define UU
Definition: newgen_types.h:98
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
#define MINUS_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define DIVIDE_OPERATOR_NAME
#define MIN_OPERATOR_NAME
entity entity_empty_label(void)
Definition: entity.c:1105
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
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
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
void AddEntityToDeclarations(entity, entity)
END_EOLE.
Definition: variable.c:108
entity make_new_index_entity(entity, string)
Definition: variable.c:1851
#define loop_body(x)
Definition: ri.h:1644
#define loop_execution(x)
Definition: ri.h:1648
#define loop_undefined
Definition: ri.h:1612
#define range_upper(x)
Definition: ri.h:2290
#define instruction_loop(x)
Definition: ri.h:1520
#define range_increment(x)
Definition: ri.h:2292
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_loop
Definition: ri.h:1471
#define execution_sequential_p(x)
Definition: ri.h:1208
#define loop_label(x)
Definition: ri.h:1646
#define range_lower(x)
Definition: ri.h:2288
#define statement_instruction(x)
Definition: ri.h:2458
#define loop_range(x)
Definition: ri.h:1642
@ is_execution_parallel
Definition: ri.h:1190
@ is_execution_sequential
Definition: ri.h:1189
#define loop_index(x)
Definition: ri.h:1640
#define statement_undefined
Definition: ri.h:2419
#define ifdebug(n)
Definition: sg.c:47

References AddEntityToDeclarations(), copy_expression(), debug(), DIVIDE_OPERATOR_NAME, entity_empty_label(), entity_intrinsic(), entity_to_expression(), entity_undefined, execution_sequential_p, expression_undefined, get_current_module_entity(), get_debug_level(), ifdebug, instruction_loop, instruction_to_statement(), int_to_expression(), is_execution_parallel, is_execution_sequential, is_instruction_loop, loop_body, loop_execution, loop_increment_value(), loop_index, loop_label, loop_range, loop_undefined, make_execution(), make_instruction(), make_loop(), make_new_index_entity(), make_op_exp(), make_range(), MakeBinaryCall(), MIN_OPERATOR_NAME, MINUS_OPERATOR_NAME, NIL, pips_assert, pips_debug, PLUS_OPERATOR_NAME, print_expression(), print_statement(), range_increment, range_lower, range_upper, statement_consistent_p(), statement_instruction, statement_undefined, user_error, and UU.

Referenced by do_kernelize(), and loop_chunk_size_and_strip_mine().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ strip_mine()

bool strip_mine ( const string  mod_name)

Top-level function.

Get the loop label form the user

DBR_CODE will be changed: argument "pure" should take false but this would be useless since there is only one version of code; a new version will be put back in the data base after strip_mineing

Reorder the module, because new statements have been generated.

Parameters
mod_nameod_name

Definition at line 233 of file strip_mine.c.

234 {
235  entity module = module_name_to_entity(mod_name);
236  statement mod_stmt;
237  const char *lp_label=NULL;
238  bool return_status;
239 
240  debug_on("STRIP_MINE_DEBUG_LEVEL");
241 
242  /* Get the loop label form the user */
243  lp_label=get_string_property_or_ask("LOOP_LABEL","Which loop do you want to strip_mine?\n" "(give its label): ");
244  if (lp_label[0] == '\0') {
245  user_log("Strip mining has been cancelled.\n");
246  return_status = false;
247  }
248  else {
249  selected_label = find_label_entity(mod_name, lp_label);
251  user_error("strip_mine", "loop label `%s' does not exist\n", lp_label);
252  }
253 
255 
256  /* DBR_CODE will be changed: argument "pure" should take false but
257  this would be useless since there is only *one* version of code;
258  a new version will be put back in the data base after
259  strip_mineing */
260  mod_stmt = (statement) db_get_memory_resource(DBR_CODE, mod_name, true);
262 
264 
265  /* Reorder the module, because new statements have been generated. */
266  module_reorder(mod_stmt);
267 
270 
271  DB_PUT_MEMORY_RESOURCE(DBR_CODE, mod_name, mod_stmt);
272  return_status = true;
273  }
274 
275  debug(2,"strip_mine","done for %s\n", mod_name);
276  debug_off();
277 
278  return return_status;
279 }
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
void look_for_nested_loop_statements(statement, statement(*)(list, bool(*)(statement)), bool(*)(statement))
look_for_nested_loops.c
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
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
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
bool selected_loop_p(statement s)
#define debug_on(env)
Definition: misc-local.h:157
#define debug_off()
Definition: misc-local.h:160
static char * module
Definition: pips.c:74
const char * get_string_property_or_ask(const char *, const char[])
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
entity find_label_entity(const char *, const char *)
util.c
Definition: util.c:43
#define entity_undefined_p(x)
Definition: ri.h:2762
entity selected_label
Interface with pipsmake for interactive loop transformations: loop interchange, hyperplane method,...
static statement loop_chunk_size_and_strip_mine(list lls, __attribute__((unused)) bool(*unused)(statement))
Hmmm...
Definition: strip_mine.c:165

References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug(), debug_off, debug_on, entity_undefined_p, find_label_entity(), get_string_property_or_ask(), look_for_nested_loop_statements(), loop_chunk_size_and_strip_mine(), module, module_name_to_entity(), module_reorder(), reset_current_module_entity(), reset_current_module_statement(), selected_label, selected_loop_p(), set_current_module_entity(), set_current_module_statement(), user_error, and user_log().

+ Here is the call graph for this function:

Variable Documentation

◆ current_module_name

char* current_module_name
extern

◆ selected_label

entity selected_label
extern

Interface with pipsmake for interactive loop transformations: loop interchange, hyperplane method,...

Definition at line 61 of file interactive_loop_transformation.c.

Referenced by strip_mine().