summaryrefslogtreecommitdiff
path: root/gcc/ipa-structure-reorg.h
blob: 0a3a87e3088c3c79c560e1539fa2eea74c600dd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/* Interprocedural structure reorganization
   Copyright (C) 2019-2020 Free Software Foundation, Inc.

  Contributed by Gary Oblock <gary@amperecomputing.com>

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

// This is depercated
#define USE_NEW_INTERFACE 1
// This is when our stuff is integrated
#define INTEGRATION_FUNCTIONAL 0
// Erick this is when you do something that really steps on some toes
#define KLUDGE 1
#define USE_REORG_TYPES 1
// If PRINT_FORMAT is true use pass specific print format.
#define PRINT_FORMAT false
// Trun off actual transformations for testing
#define BYPASS_TRANSFORM false

typedef struct RT_Elim       RT_Elim;
typedef struct RT_Reorder    RT_Reorder;
typedef struct RT_Interleave RT_Interleave;

#include <set>
#include "collect-types.h"

struct RT_Elim {
  int dummy;
};

struct RT_Reorder {
  int dummy;
};

struct RT_Interleave {
  int        numbOfGlobalArrays; // Statically allocated only
  int        numbOfLocalArrays;  // Statically allocated only
  int        numbOfDynmAllocs;
  tree       base;
  double     reorg_perf;         
  double     regular_perf;
  bool       multi_pool;         // single pool if not set
  int        dummy;
};

typedef struct ReorgType ReorgType_t;
// TODO: Gary, is there supposed to be 
// 1 ReorgType_t for every tree?
// Don't we need something that also is global?
// I have a set of trees that do not escape
// and I would like to use that for the moment.
// Not sure how it will evolve in the future...
// REPLY: Erick, I'm not sure I follow what you
// are asking. In my mind there should
// be one reorg type for every unique type and
// if some N types are equivalent then there should
// be only one reorg type for all of them.
struct ReorgType {
  unsigned      id;
  bool          delete_me;
  tree          gcc_type;           // This info is for this type.
  // TBD will field reordering and/or dead field elimination use
  // use the reorg_ver_type? I think it's likely that they can.
  tree          reorg_ver_type;     // the base type
  tree          pointer_rep;        // new pointer format (multi-pool)
  bool          do_dead_field_elim;
  bool          do_field_reorder;
  bool          do_instance_interleave;
  RT_Elim       dead_field_elim;
  RT_Reorder    field_reorder;
  RT_Interleave instance_interleave;
};

typedef struct ProgDecl ProgDecl_t;
struct ProgDecl {
  tree       gcc_decl;
};

enum ReorgOpTrans {
  // TODO: What is the purpose of this enum?
  // Let's try to use scalar insead of this... nope!
  ReorgOpT_Temp,         // SSA temp
  ReorgOpT_Address,     // "&x[i]"
  ReorgOpT_Pointer,     // "a"
  ReorgOpT_Struct,      // "s"
  ReorgOpT_Deref,       // "*a"
  ReorgOpT_Array,       // "x[i]"
  ReorgOpT_Scalar,      // "z"
  ReorgOpT_Indirect,    // "a->f"
  ReorgOpT_AryDir,      // "x[i].f"
  ReorgOpT_Cst,
  ReorgOpT_Cst0
};

enum CompressionControl {
  Initial,
  Subsequent
};

enum ReorgTransformation {
  // TODO: Gary, if these are transformation, shouldn't they have
  // a pre-state and a post-state?
  // Here I am only seeing statements. Not sure why 
  // a reorg transformation has statements / expressions.
  //
  // Also, why aren't we using the expressions already
  // defined by GCC? For example EQ_EXPR?
  // Ultimately what is the purpose of these?
  ReorgT_StrAssign,    // "*a = x[i]", "x[i] = y[j]", "s = *a", etc.
  ReorgT_ElemAssign,   // "a->f = z", "z = x[i].f", etc.
  ReorgT_If_Null,      // "if(a == 0)..."
  ReorgT_If_NotNull,   // "if(a != 0)..."
  ReorgT_IfPtrEQ,      // "if(a == b)..."
  ReorgT_IfPtrNE,      // "if(a != b)..."
  ReorgT_IfPtrLT,      // "if(a < b)..."
  ReorgT_IfPtrGT,      // "if(a > b)..."
  ReorgT_IfPtrLE,      // "if(a <= b)..."
  ReorgT_IfPtrGE,      // "if(a >= b)..."
  ReorgT_PtrPlusInt,   // "a = b + i"
  ReorgT_Ptr2Zero,     // "a = 0"
  ReorgT_PtrDiff,      // "i = a - b"
  ReorgT_Adr2Ptr,      // "a = &x[i]"
  ReorgT_PtrNull,      // "x = a == 0"
  ReorgT_PtrNotNull,   // "x = a != 0"
  ReorgT_PtrEQ,        // "x = a == b"
  ReorgT_PtrNE,        // "x = a != b"
  ReorgT_PtrLT,        // "x = a < b"
  ReorgT_PtrLE,        // "x = a <= b"
  ReorgT_PtrGT,        // "x = a > b"
  ReorgT_PtrGE,        // "x = a >= b"
  ReorgT_Malloc,       //
  ReorgT_Calloc,       //
  ReorgT_Realloc,      //
  ReorgT_Free,         //
  ReorgT_UserFunc,     //
  ReorgT_Convert,      // type casts
  ReorgT_Return,       // return t
  Not_Supported
};

// Added as design bug fix
typedef struct BoolPair BoolPair_t;
struct BoolPair {
  bool processed;
  bool layout_changed;
};

typedef struct Info Info_t;
struct Info {
  // TODO: What is the meaning of reorg type?
  // Hasn't this meaning changed now that we have three
  // transformations roughly running at the same time?
  // Eric: Interesting point
  std::vector <ReorgType_t>      *reorg_type;
  // Added to by remove_deleted_types
  std::vector <ReorgType_t>      *saved_reorg_type;
  std::vector <ProgDecl_t>       *prog_decl;
  // Gcc doesn't have global decls readily available
  // so this holds them
  std::map <tree,BoolPair_t>     *struct_types; // desing bug fix
  // ptrset_t holds types which point to records
  // and types which escape
  ptrset_t sets;
  int                             num_deleted;
  double                          total_cache_accesses;
  FILE                           *reorg_dump_file;
  // Debug flags
  bool                            show_all_reorg_cands;
  bool                            show_all_reorg_cands_in_detail;
  bool                            show_perf_qualify;
  bool                            show_prog_decls;
  bool                            show_delete;
  bool                            show_new_BBs;
  bool                            show_transforms;
  bool                            show_bounds;
  bool                            is_non_escaping_set_empty();

  Info (std::vector <ReorgType_t> *v1,
        std::vector <ReorgType_t> *v2,
	std::vector <ProgDecl_t> *v3,
	std::map <tree, BoolPair_t> *v4)
  : reorg_type(v1)
  , saved_reorg_type(v2)
  , prog_decl(v3)
  , struct_types(v4)
  , num_deleted(0)
  , total_cache_accesses(0)
  , reorg_dump_file(NULL)
  , show_all_reorg_cands(false)
  , show_all_reorg_cands_in_detail(false)
  , show_perf_qualify(false)
  , show_prog_decls(false)
  , show_new_BBs(false)
  , show_transforms(false)
  , show_bounds(false)
  {};
};

// This will perform a function on the supplied
// reorg type. It's primarily to support debugging.
typedef void (*ReorgFn)( Info *, ReorgType_t *);

#define USE_NEW_INTERFACE 1
#if USE_NEW_INTERFACE
extern int str_reorg_dead_field_eliminate_qual ( Info *);
extern int str_reorg_dead_field_eliminate_trans ( Info *);
extern int str_reorg_field_reorder_qual ( Info *);
extern int str_reorg_field_reorder_trans ( Info *);
extern int str_reorg_instance_interleave_qual ( Info *);
extern int str_reorg_instance_interleave_trans ( Info *);
#else
extern int str_reorg_dead_field_eliminate ( Info *);
extern int str_reorg_field_reorder ( Info *);
extern int str_reorg_instance_interleave ( Info *);
#endif

extern int number_of_levels ( tree);
extern tree make_multilevel( tree, int);
extern bool modify_decl_core ( tree *, Info *);
extern void delete_reorgtype ( ReorgType_t *, Info_t *);
extern void undelete_reorgtype ( ReorgType_t *, Info_t *);
extern void clear_deleted_types( Info *);
extern void restore_deleted_types ( Info *);
extern void remove_deleted_types ( Info *, ReorgFn);
extern enum ReorgOpTrans recognize_op ( tree,  bool, Info_t *);
extern ReorgTransformation reorg_recognize ( gimple *,
					     cgraph_node *,
					     Info_t *);
extern void apply_to_all_gimple ( bool (*)(gimple *, void *), bool, void *);
extern ReorgType_t *get_reorgtype_info ( tree, Info_t *);
extern void print_reorg_with_msg ( FILE *, ReorgType_t *, int, const char *);
extern ReorgType_t *contains_a_reorgtype ( gimple *, Info *);
extern bool tree_contains_a_reorgtype_p ( tree, Info *);
extern ReorgType_t *tree_contains_a_reorgtype ( tree, Info *);
extern bool is_reorg_type ( tree, Info_t *);
extern tree base_type_of ( tree);
extern tree base_type_with_levels ( tree, int *);
extern void print_reorg ( FILE *, int, ReorgType_t *);
extern void print_program ( FILE *, bool, int, Info_t *);
extern void print_type ( FILE *, tree);
extern void modify_ssa_name_type ( tree, tree);
extern bool print_internals (gimple *, void *);
extern const char *optrans_to_str ( enum ReorgOpTrans);
extern bool is_assign_from_ssa ( gimple *);



// I have no intention of leaving these debugging marcos or uses of
// them in the code. However, some of the uses should obviously be
// converted to dump file information.

#define DEBUGGING 1
#if DEBUGGING
enum Display {
  Show_nothing,
  Show_failures,
  Show_everything
};

enum Failure {
  Do_not_fail,
  Fail_1st_bad,
  Fail_at_End
};

extern int debug_indenting;
extern void handle_debug_indenting( int);
extern const char *code_str( enum tree_code);
extern void wolf_fence( Info *);
extern bool ssa_check ( FILE *, Display, Failure, bool, bool);

// Line numbered
#define DEBUG_L(...) { fprintf( stderr, "L# %4d: %*s", __LINE__, debug_indenting, ""); fprintf( stderr, __VA_ARGS__); }
// Alinged with line numbered
#define DEBUG_A(...) { fprintf( stderr, "%*s", debug_indenting + 7, ""); fprintf( stderr, __VA_ARGS__); }
//With no indenting
#define DEBUG(...) { fprintf( stderr, __VA_ARGS__); }
#define DEBUG_F(f,...) f( __VA_ARGS__)
#define INDENT(a) handle_debug_indenting(a)
#else
#define DEBUG_L(...)
#define DEBUG_A(...)
#define DEBUG(...)
#define DEBUG_F(...)
#define INDENT(a)

#endif
extern void flexible_print( FILE *, tree, int, dump_flags_t);