benode.c 40 KB
Newer Older
Sebastian Hack's avatar
Sebastian Hack committed
1
2
3
4
5
6
7
/**
 * @file   benode.c
 * @date   17.05.2005
 * @author Sebastian Hack
 *
 * Backend node support.
 *
Michael Beck's avatar
Michael Beck committed
8
 * This file provides Perm, Copy, Spill and Reload nodes.
9
 *
Sebastian Hack's avatar
Sebastian Hack committed
10
11
12
 * Copyright (C) 2005 Universitaet Karlsruhe
 * Released under the GPL
 */
13

Michael Beck's avatar
Michael Beck committed
14
15
16
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Sebastian Hack's avatar
Sebastian Hack committed
17
18
19
20
21
22

#include <stdlib.h>

#include "obst.h"
#include "set.h"
#include "pmap.h"
23
#include "util.h"
Sebastian Hack's avatar
Sebastian Hack committed
24
#include "debug.h"
25
#include "fourcc.h"
Sebastian Hack's avatar
Sebastian Hack committed
26
#include "offset.h"
Sebastian Hack's avatar
Sebastian Hack committed
27
#include "bitfiddle.h"
Sebastian Hack's avatar
Sebastian Hack committed
28
29
30
31

#include "irop_t.h"
#include "irmode_t.h"
#include "irnode_t.h"
32
#include "ircons_t.h"
33
#include "irprintf.h"
Sebastian Hack's avatar
Sebastian Hack committed
34
#include "irgwalk.h"
Michael Beck's avatar
Michael Beck committed
35
#include "iropt_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
36

37
38
39
#include "be_t.h"
#include "belive_t.h"
#include "besched_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
40
41
#include "benode_t.h"

42
43
#include "beirgmod.h"

Sebastian Hack's avatar
Sebastian Hack committed
44
45
#define OUT_POS(x) (-((x) + 1))

Sebastian Hack's avatar
Sebastian Hack committed
46
47
/* Sometimes we want to put const nodes into get_irn_generic_attr ... */
#define get_irn_attr(irn) get_irn_generic_attr((ir_node *) (irn))
Daniel Grund's avatar
Daniel Grund committed
48

Sebastian Hack's avatar
Sebastian Hack committed
49
static unsigned be_node_tag = FOURCC('B', 'E', 'N', 'O');
50

Sebastian Hack's avatar
Sebastian Hack committed
51
#if 0
Sebastian Hack's avatar
Sebastian Hack committed
52
typedef enum _node_kind_t {
Christian Würdig's avatar
Christian Würdig committed
53
54
55
56
	node_kind_spill,
	node_kind_reload,
	node_kind_perm,
	node_kind_copy,
Sebastian Hack's avatar
Sebastian Hack committed
57
	node_kind_kill,
Christian Würdig's avatar
Christian Würdig committed
58
	node_kind_last
Sebastian Hack's avatar
Sebastian Hack committed
59
} node_kind_t;
Sebastian Hack's avatar
Sebastian Hack committed
60
#endif
Sebastian Hack's avatar
Sebastian Hack committed
61

Sebastian Hack's avatar
Sebastian Hack committed
62
63
64
65
66
67
typedef enum {
	be_req_kind_old_limited,
	be_req_kind_negate_old_limited,
	be_req_kind_single_reg
} be_req_kind_t;

Sebastian Hack's avatar
Sebastian Hack committed
68
69
typedef struct {
	arch_register_req_t req;
Sebastian Hack's avatar
Sebastian Hack committed
70
	be_req_kind_t       kind;
Sebastian Hack's avatar
Sebastian Hack committed
71
	arch_irn_flags_t    flags;
Sebastian Hack's avatar
Sebastian Hack committed
72
73
74
75
76
77
78
79
	union {
		struct {
			void (*old_limited)(void *ptr, bitset_t *bs);
			void *old_limited_env;
		} old_limited;

		const arch_register_t *single_reg;
	} x;
Sebastian Hack's avatar
Sebastian Hack committed
80
81
} be_req_t;

82
typedef struct {
83
	const arch_register_t *reg;
Sebastian Hack's avatar
Sebastian Hack committed
84
	be_req_t              req;
Sebastian Hack's avatar
Sebastian Hack committed
85
	be_req_t              in_req;
86
87
} be_reg_data_t;

88
/** The generic be nodes attribute type. */
89
typedef struct {
90
91
	int                   max_reg_data;
	be_reg_data_t         *reg_data;
92
93
} be_node_attr_t;

94
95
96
97
98
99
/** The be_Return nodes attribute type. */
typedef struct {
	be_node_attr_t node_attr;
	int            num_ret_vals;  /**< number of return values */
} be_return_attr_t;

100
/** The be_Stack attribute type. */
Sebastian Hack's avatar
Sebastian Hack committed
101
102
103
typedef struct {
	be_node_attr_t node_attr;
	int offset;           /**< The offset by which the stack shall be increased/decreased. */
104
	be_stack_dir_t dir;   /**< The direction in which the stack shall be modified (expand or shrink). */
Sebastian Hack's avatar
Sebastian Hack committed
105
106
} be_stack_attr_t;

107
/** The be_Frame attribute type. */
108
109
110
111
112
113
typedef struct {
	be_node_attr_t node_attr;
	entity *ent;
	int offset;
} be_frame_attr_t;

114
/** The be_Call attribute type. */
115
116
typedef struct {
	be_node_attr_t node_attr;
117
118
	entity *ent;         /**< The called entity if this is a static call. */
	ir_type *call_tp;    /**< The call type, copied from the original Call node. */
119
120
} be_call_attr_t;

121
/** The be_Spill attribute type. */
122
123
124
125
126
typedef struct {
	be_frame_attr_t frame_attr;
	ir_node *spill_ctx;  /**< The node in whose context this spill was introduced. */
} be_spill_attr_t;

127
128
129
130
131
ir_op *op_be_Spill;
ir_op *op_be_Reload;
ir_op *op_be_Perm;
ir_op *op_be_Copy;
ir_op *op_be_Keep;
Sebastian Hack's avatar
Sebastian Hack committed
132
ir_op *op_be_CopyKeep;
133
134
135
ir_op *op_be_Call;
ir_op *op_be_Return;
ir_op *op_be_IncSP;
Sebastian Hack's avatar
Sebastian Hack committed
136
ir_op *op_be_AddSP;
137
138
139
140
141
142
ir_op *op_be_SetSP;
ir_op *op_be_RegParams;
ir_op *op_be_StackParam;
ir_op *op_be_FrameAddr;
ir_op *op_be_FrameLoad;
ir_op *op_be_FrameStore;
143
ir_op *op_be_Barrier;
Sebastian Hack's avatar
Sebastian Hack committed
144

Sebastian Hack's avatar
Sebastian Hack committed
145
static int beo_base = -1;
Sebastian Hack's avatar
Sebastian Hack committed
146

Sebastian Hack's avatar
Sebastian Hack committed
147
static const ir_op_ops be_node_op_ops;
Sebastian Hack's avatar
Sebastian Hack committed
148

149
150
151
152
153
154
155
156
157
158
#define N   irop_flag_none
#define L   irop_flag_labeled
#define C   irop_flag_commutative
#define X   irop_flag_cfopcode
#define I   irop_flag_ip_cfopcode
#define F   irop_flag_fragile
#define Y   irop_flag_forking
#define H   irop_flag_highlevel
#define c   irop_flag_constlike
#define K   irop_flag_keep
159
160
#define M   irop_flag_machine

161

Michael Beck's avatar
Michael Beck committed
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
/**
 * Compare two node attributes.
 *
 * @return zero if both attributes are identically
 */
static int cmp_node_attr(be_node_attr_t *a, be_node_attr_t *b) {
	if (a->max_reg_data == b->max_reg_data) {
		int i;

		for (i = 0; i < a->max_reg_data; ++i) {
			if (a->reg_data[i].reg    != b->reg_data[i].reg ||
			    memcmp(&a->reg_data[i].in_req, &b->reg_data[i].in_req, sizeof(b->reg_data[i].in_req)) ||
			    memcmp(&a->reg_data[i].req,    &b->reg_data[i].req,    sizeof(a->reg_data[i].req)))
				return 1;
		}
		return 0;
	}
	return 1;
}

/**
 * Compare the attributes of two FrameAddr nodes.
 *
 * @return zero if both attributes are identically
 */
static int FrameAddr_cmp_attr(ir_node *a, ir_node *b) {
	be_frame_attr_t *a_attr = get_irn_attr(a);
	be_frame_attr_t *b_attr = get_irn_attr(b);

191
192
193
	if (a_attr->ent == b_attr->ent && a_attr->offset == b_attr->offset)
		return cmp_node_attr(&a_attr->node_attr, &b_attr->node_attr);
	return 1;
Michael Beck's avatar
Michael Beck committed
194
195
}

Sebastian Hack's avatar
Sebastian Hack committed
196
197
void be_node_init(void) {
	static int inited = 0;
Sebastian Hack's avatar
Sebastian Hack committed
198

Sebastian Hack's avatar
Sebastian Hack committed
199
200
	if(inited)
		return;
Sebastian Hack's avatar
Sebastian Hack committed
201

Sebastian Hack's avatar
Sebastian Hack committed
202
	inited = 1;
Sebastian Hack's avatar
Sebastian Hack committed
203

204
205
	/* Acquire all needed opcodes. */
	beo_base = get_next_ir_opcodes(beo_Last - 1);
Sebastian Hack's avatar
Sebastian Hack committed
206

207
208
209
210
211
212
213
214
215
216
217
218
219
	op_be_Spill      = new_ir_op(beo_base + beo_Spill,      "be_Spill",      op_pin_state_mem_pinned, N, oparity_unary,    0, sizeof(be_spill_attr_t),  &be_node_op_ops);
	op_be_Reload     = new_ir_op(beo_base + beo_Reload,     "be_Reload",     op_pin_state_mem_pinned, N, oparity_zero,     0, sizeof(be_frame_attr_t),  &be_node_op_ops);
	op_be_Perm       = new_ir_op(beo_base + beo_Perm,       "be_Perm",       op_pin_state_pinned,     N, oparity_variable, 0, sizeof(be_node_attr_t),   &be_node_op_ops);
	op_be_Copy       = new_ir_op(beo_base + beo_Copy,       "be_Copy",       op_pin_state_floats,     N, oparity_unary,    0, sizeof(be_node_attr_t),   &be_node_op_ops);
	op_be_Keep       = new_ir_op(beo_base + beo_Keep,       "be_Keep",       op_pin_state_pinned,     K, oparity_variable, 0, sizeof(be_node_attr_t),   &be_node_op_ops);
	op_be_CopyKeep   = new_ir_op(beo_base + beo_CopyKeep,   "be_CopyKeep",   op_pin_state_pinned,     K, oparity_variable, 0, sizeof(be_node_attr_t),   &be_node_op_ops);
	op_be_Call       = new_ir_op(beo_base + beo_Call,       "be_Call",       op_pin_state_pinned,     N, oparity_variable, 0, sizeof(be_call_attr_t),   &be_node_op_ops);
	op_be_Return     = new_ir_op(beo_base + beo_Return,     "be_Return",     op_pin_state_pinned,     X, oparity_variable, 0, sizeof(be_return_attr_t), &be_node_op_ops);
	op_be_AddSP      = new_ir_op(beo_base + beo_AddSP,      "be_AddSP",      op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_node_attr_t),   &be_node_op_ops);
	op_be_SetSP      = new_ir_op(beo_base + beo_SetSP,      "be_SetSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t),  &be_node_op_ops);
	op_be_IncSP      = new_ir_op(beo_base + beo_IncSP,      "be_IncSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t),  &be_node_op_ops);
	op_be_RegParams  = new_ir_op(beo_base + beo_RegParams,  "be_RegParams",  op_pin_state_pinned,     N, oparity_zero,     0, sizeof(be_node_attr_t),   &be_node_op_ops);
	op_be_StackParam = new_ir_op(beo_base + beo_StackParam, "be_StackParam", op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_frame_attr_t),  &be_node_op_ops);
Michael Beck's avatar
Michael Beck committed
220
	op_be_FrameAddr  = new_ir_op(beo_base + beo_FrameAddr,  "be_FrameAddr",  op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_frame_attr_t),  &be_node_op_ops);
221
222
223
	op_be_FrameLoad  = new_ir_op(beo_base + beo_FrameLoad,  "be_FrameLoad",  op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t),  &be_node_op_ops);
	op_be_FrameStore = new_ir_op(beo_base + beo_FrameStore, "be_FrameStore", op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t),  &be_node_op_ops);
	op_be_Barrier    = new_ir_op(beo_base + beo_Barrier,    "be_Barrier",    op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_node_attr_t),   &be_node_op_ops);
224
225
226
227
228
229

	set_op_tag(op_be_Spill,      &be_node_tag);
	set_op_tag(op_be_Reload,     &be_node_tag);
	set_op_tag(op_be_Perm,       &be_node_tag);
	set_op_tag(op_be_Copy,       &be_node_tag);
	set_op_tag(op_be_Keep,       &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
230
	set_op_tag(op_be_CopyKeep,   &be_node_tag);
231
232
	set_op_tag(op_be_Call,       &be_node_tag);
	set_op_tag(op_be_Return,     &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
233
	set_op_tag(op_be_AddSP,      &be_node_tag);
234
235
236
237
238
239
240
	set_op_tag(op_be_SetSP,      &be_node_tag);
	set_op_tag(op_be_IncSP,      &be_node_tag);
	set_op_tag(op_be_RegParams,  &be_node_tag);
	set_op_tag(op_be_StackParam, &be_node_tag);
	set_op_tag(op_be_FrameLoad,  &be_node_tag);
	set_op_tag(op_be_FrameStore, &be_node_tag);
	set_op_tag(op_be_FrameAddr,  &be_node_tag);
241
	set_op_tag(op_be_Barrier,    &be_node_tag);
Michael Beck's avatar
Michael Beck committed
242
243

	op_be_FrameAddr->ops.node_cmp_attr = FrameAddr_cmp_attr;
Sebastian Hack's avatar
Sebastian Hack committed
244
}
245

246
247
248
/**
 * Initializes the generic attribute of all be nodes and return ir.
 */
Sebastian Hack's avatar
Sebastian Hack committed
249
static void *init_node_attr(ir_node* irn, int max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
250
{
Sebastian Hack's avatar
Sebastian Hack committed
251
	ir_graph *irg     = get_irn_irg(irn);
Sebastian Hack's avatar
Sebastian Hack committed
252
253
	be_node_attr_t *a = get_irn_attr(irn);

254
	memset(a, 0, sizeof(get_op_attr_size(get_irn_op(irn))));
Sebastian Hack's avatar
Sebastian Hack committed
255
256
	a->max_reg_data = max_reg_data;
	a->reg_data     = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
257

Sebastian Hack's avatar
Sebastian Hack committed
258
	if(max_reg_data > 0) {
Sebastian Hack's avatar
Sebastian Hack committed
259
260
		int i;

Sebastian Hack's avatar
Sebastian Hack committed
261
262
263
		a->reg_data = NEW_ARR_D(be_reg_data_t, get_irg_obstack(irg), max_reg_data);
		memset(a->reg_data, 0, max_reg_data * sizeof(a->reg_data[0]));
		for(i = 0; i < max_reg_data; ++i) {
Sebastian Hack's avatar
Sebastian Hack committed
264
265
			a->reg_data[i].req.req.cls  = NULL;
			a->reg_data[i].req.req.type = arch_register_req_type_none;
Sebastian Hack's avatar
Sebastian Hack committed
266
267
268
269
270
		}
	}

	return a;
}
271

272
int is_be_node(const ir_node *irn)
273
{
Sebastian Hack's avatar
Sebastian Hack committed
274
	return get_op_tag(get_irn_op(irn)) == &be_node_tag;
275
276
}

Sebastian Hack's avatar
Sebastian Hack committed
277
be_opcode_t be_get_irn_opcode(const ir_node *irn)
278
{
Sebastian Hack's avatar
Sebastian Hack committed
279
	return is_be_node(irn) ? get_irn_opcode(irn) - beo_base : beo_NoBeOp;
280
281
}

Sebastian Hack's avatar
Sebastian Hack committed
282
283
284
285
286
static int redir_proj(const ir_node **node, int pos)
{
	const ir_node *n = *node;

	if(is_Proj(n)) {
287
288
		ir_node *irn;

Sebastian Hack's avatar
Sebastian Hack committed
289
		assert(pos == -1 && "Illegal pos for a Proj");
290
291
292
293
294
		*node = irn = get_Proj_pred(n);
		if(is_Proj(irn)) {
			assert(get_irn_mode(irn) == mode_T);
			*node = get_Proj_pred(irn);
		}
Sebastian Hack's avatar
Sebastian Hack committed
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
		return get_Proj_proj(n);
	}

	return 0;
}

static void
be_node_set_irn_reg(const void *_self, ir_node *irn, const arch_register_t *reg)
{
	int out_pos;
	be_node_attr_t *a;

	out_pos = redir_proj((const ir_node **) &irn, -1);
	a       = get_irn_attr(irn);

	assert(is_be_node(irn));
Sebastian Hack's avatar
Sebastian Hack committed
311
	assert(out_pos < a->max_reg_data && "position too high");
Sebastian Hack's avatar
Sebastian Hack committed
312
313
314
315
	a->reg_data[out_pos].reg = reg;
}


Sebastian Hack's avatar
Sebastian Hack committed
316
ir_node *be_new_Spill(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *to_spill, ir_node *ctx)
317
{
Sebastian Hack's avatar
Sebastian Hack committed
318
	be_spill_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
319
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
320
	ir_node *res;
321

Sebastian Hack's avatar
Sebastian Hack committed
322
323
	in[0] = frame;
	in[1] = to_spill;
324
	res   = new_ir_node(NULL, irg, bl, op_be_Spill, mode_M, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
325
	a     = init_node_attr(res, 2);
326
327
	a->frame_attr.ent = NULL;
	a->frame_attr.offset = 0;
Sebastian Hack's avatar
Sebastian Hack committed
328
	a->spill_ctx = ctx;
Sebastian Hack's avatar
Sebastian Hack committed
329
330
331

	be_node_set_reg_class(res, 0, cls_frame);
	be_node_set_reg_class(res, 1, cls);
Sebastian Hack's avatar
Sebastian Hack committed
332
333
	return res;
}
334

Sebastian Hack's avatar
Sebastian Hack committed
335
ir_node *be_new_Reload(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *mem, ir_mode *mode)
336
{
Sebastian Hack's avatar
Sebastian Hack committed
337
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
338
	ir_node *res;
339

Sebastian Hack's avatar
Sebastian Hack committed
340
341
	in[0] = frame;
	in[1] = mem;
342
	res   = new_ir_node(NULL, irg, bl, op_be_Reload, mode, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
343
344
345
	init_node_attr(res, 2);
	be_node_set_reg_class(res, 0, cls_frame);
	be_node_set_reg_class(res, -1, cls);
Sebastian Hack's avatar
Sebastian Hack committed
346
347
	return res;
}
348

349
ir_node *be_get_Reload_mem(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
350
351
{
	assert(be_is_Reload(irn));
Daniel Grund's avatar
Daniel Grund committed
352
	return get_irn_n(irn, be_pos_Reload_mem);
Sebastian Hack's avatar
Sebastian Hack committed
353
354
}

355
356
357
358
359
360
ir_node *be_get_Reload_frame(const ir_node *irn)
{
	assert(be_is_Reload(irn));
	return get_irn_n(irn, be_pos_Reload_frame);
}

Sebastian Hack's avatar
Sebastian Hack committed
361
362
ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
{
Sebastian Hack's avatar
Sebastian Hack committed
363
	int i;
364
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Perm, mode_T, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
365
366
367
368
369
370
	init_node_attr(irn, n);
	for(i = 0; i < n; ++i) {
		be_node_set_reg_class(irn, i, cls);
		be_node_set_reg_class(irn, OUT_POS(i), cls);
	}

Sebastian Hack's avatar
Sebastian Hack committed
371
372
	return irn;
}
373

Sebastian Hack's avatar
Sebastian Hack committed
374
375
376
377
ir_node *be_new_Copy(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *op)
{
	ir_node *in[1];
	ir_node *res;
378

Sebastian Hack's avatar
Sebastian Hack committed
379
	in[0] = op;
380
	res   = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
381
382
383
	init_node_attr(res, 1);
	be_node_set_reg_class(res, 0, cls);
	be_node_set_reg_class(res, OUT_POS(0), cls);
Sebastian Hack's avatar
Sebastian Hack committed
384
	return res;
385
386
}

387
388
389
390
ir_node *be_get_Copy_op(const ir_node *cpy) {
	return get_irn_n(cpy, be_pos_Copy_op);
}

391
392
393
394
void be_set_Copy_op(ir_node *cpy, ir_node *op) {
	set_irn_n(cpy, be_pos_Copy_op, op);
}

Sebastian Hack's avatar
Sebastian Hack committed
395
ir_node *be_new_Keep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
Sebastian Hack's avatar
Sebastian Hack committed
396
{
Sebastian Hack's avatar
Sebastian Hack committed
397
	int i;
Sebastian Hack's avatar
Sebastian Hack committed
398
	ir_node *irn;
Sebastian Hack's avatar
Sebastian Hack committed
399

400
	irn = new_ir_node(NULL, irg, bl, op_be_Keep, mode_ANY, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
401
402
403
404
	init_node_attr(irn, n);
	for(i = 0; i < n; ++i) {
		be_node_set_reg_class(irn, i, cls);
	}
Sebastian Hack's avatar
Sebastian Hack committed
405
406
	keep_alive(irn);
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
407
408
}

409
410
ir_node *be_new_Call(dbg_info *dbg, ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *sp, ir_node *ptr,
                     int n_outs, int n, ir_node *in[], ir_type *call_tp)
Sebastian Hack's avatar
Sebastian Hack committed
411
{
412
413
	be_call_attr_t *a;
	int real_n = be_pos_Call_first_arg + n;
Sebastian Hack's avatar
Sebastian Hack committed
414
415
	ir_node *irn;
	ir_node **real_in;
Sebastian Hack's avatar
Sebastian Hack committed
416

417
418
419
420
421
	NEW_ARR_A(ir_node *, real_in, real_n);
	real_in[be_pos_Call_mem] = mem;
	real_in[be_pos_Call_sp]  = sp;
	real_in[be_pos_Call_ptr] = ptr;
	memcpy(&real_in[be_pos_Call_first_arg], in, n * sizeof(in[0]));
Sebastian Hack's avatar
Sebastian Hack committed
422

423
	irn = new_ir_node(dbg, irg, bl, op_be_Call, mode_T, real_n, real_in);
424
425
426
	a = init_node_attr(irn, (n_outs > real_n ? n_outs : real_n));
	a->ent     = NULL;
	a->call_tp = call_tp;
Sebastian Hack's avatar
Sebastian Hack committed
427
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
428
429
}

430
431
/* Gets the call entity or NULL if this is no static call. */
entity *be_Call_get_entity(const ir_node *call) {
432
433
434
435
436
	be_call_attr_t *a = get_irn_attr(call);
	assert(be_is_Call(call));
	return a->ent;
}

437
438
/* Sets the call entity. */
void be_Call_set_entity(ir_node *call, entity *ent) {
439
440
441
442
443
	be_call_attr_t *a = get_irn_attr(call);
	assert(be_is_Call(call));
	a->ent = ent;
}

444
445
446
447
448
449
450
451
452
453
454
455
456
457
/* Gets the call type. */
ir_type *be_Call_get_type(ir_node *call) {
	be_call_attr_t *a = get_irn_attr(call);
	assert(be_is_Call(call));
	return a->call_tp;
}

/* Sets the call type. */
void be_Call_set_type(ir_node *call, ir_type *call_tp) {
	be_call_attr_t *a = get_irn_attr(call);
	assert(be_is_Call(call));
	a->call_tp = call_tp;
}

458
459
/* Construct a new be_Return. */
ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *bl, int n_res, int n, ir_node *in[])
Sebastian Hack's avatar
Sebastian Hack committed
460
{
461
	be_return_attr_t *a;
462
	ir_node *irn = new_ir_node(dbg, irg, bl, op_be_Return, mode_X, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
463
	init_node_attr(irn, n);
464
465
	a = get_irn_attr(irn);
	a->num_ret_vals = n_res;
Sebastian Hack's avatar
Sebastian Hack committed
466
467
468
469

	return irn;
}

470
471
472
473
474
475
476
/* Returns the number of real returns values */
int be_Return_get_n_rets(ir_node *ret)
{
	be_return_attr_t *a = get_irn_attr(ret);
	return a->num_ret_vals;
}

477
ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *mem, unsigned offset, be_stack_dir_t dir)
Sebastian Hack's avatar
Sebastian Hack committed
478
{
Sebastian Hack's avatar
Sebastian Hack committed
479
480
	be_stack_attr_t *a;
	ir_node *irn;
481
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
482
483

	in[0]     = old_sp;
484
	in[1]     = mem;
485
	irn       = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
486
	a         = init_node_attr(irn, 1);
Sebastian Hack's avatar
Sebastian Hack committed
487
488
489
	a->dir    = dir;
	a->offset = offset;

490
	be_node_set_flags(irn, -1, arch_irn_flags_ignore | arch_irn_flags_modify_sp);
Sebastian Hack's avatar
Sebastian Hack committed
491

Sebastian Hack's avatar
Sebastian Hack committed
492
	/* Set output constraint to stack register. */
Sebastian Hack's avatar
Sebastian Hack committed
493
	be_node_set_reg_class(irn, 0, sp->reg_class);
Sebastian Hack's avatar
Sebastian Hack committed
494
	be_set_constr_single_reg(irn, -1, sp);
Sebastian Hack's avatar
Sebastian Hack committed
495
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
496
497

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
498
}
Sebastian Hack's avatar
Sebastian Hack committed
499

Sebastian Hack's avatar
Sebastian Hack committed
500
ir_node *be_new_AddSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *sz)
Sebastian Hack's avatar
Sebastian Hack committed
501
{
Sebastian Hack's avatar
Sebastian Hack committed
502
	be_node_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
503
	ir_node *irn;
Sebastian Hack's avatar
Sebastian Hack committed
504
	ir_node *in[be_pos_AddSP_last];
Sebastian Hack's avatar
Sebastian Hack committed
505

Sebastian Hack's avatar
Sebastian Hack committed
506
507
	in[be_pos_AddSP_old_sp] = old_sp;
	in[be_pos_AddSP_size]   = sz;
Sebastian Hack's avatar
Sebastian Hack committed
508

Sebastian Hack's avatar
Sebastian Hack committed
509
510
511
	irn      = new_ir_node(NULL, irg, bl, op_be_AddSP, mode_T, be_pos_AddSP_last, in);
	a        = init_node_attr(irn, be_pos_AddSP_last);

512
	be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore | arch_irn_flags_modify_sp);
Sebastian Hack's avatar
Sebastian Hack committed
513
514

	/* Set output constraint to stack register. */
Sebastian Hack's avatar
Sebastian Hack committed
515
	be_set_constr_single_reg(irn, OUT_POS(0), sp);
Sebastian Hack's avatar
Sebastian Hack committed
516
517
518
519
520
521
522
523
524
525
526
527
528

	return irn;
}

ir_node *be_new_SetSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *op, ir_node *mem)
{
	be_node_attr_t *a;
	ir_node *irn;
	ir_node *in[3];

	in[0]    = mem;
	in[1]    = old_sp;
	in[2]    = op;
529
	irn      = new_ir_node(NULL, irg, bl, op_be_SetSP, get_irn_mode(old_sp), 3, in);
Sebastian Hack's avatar
Sebastian Hack committed
530
531
	a        = init_node_attr(irn, 3);

532
	be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore | arch_irn_flags_modify_sp);
Sebastian Hack's avatar
Sebastian Hack committed
533
534
535
536
537

	/* Set output constraint to stack register. */
	be_set_constr_single_reg(irn, OUT_POS(0), sp);
	be_node_set_reg_class(irn, 1, sp->reg_class);
	be_node_set_reg_class(irn, 2, sp->reg_class);
Sebastian Hack's avatar
Sebastian Hack committed
538
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
539
540

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
541
}
Sebastian Hack's avatar
Sebastian Hack committed
542

Sebastian Hack's avatar
Sebastian Hack committed
543
ir_node *be_new_StackParam(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_mode *mode, ir_node *frame_pointer, entity *ent)
Sebastian Hack's avatar
Sebastian Hack committed
544
{
545
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
546
547
548
	ir_node *irn;
	ir_node *in[1];

549
	in[0] = frame_pointer;
550
	irn = new_ir_node(NULL, irg, bl, op_be_StackParam, mode, 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
551
	a = init_node_attr(irn, 1);
552
	a->ent = ent;
Sebastian Hack's avatar
Sebastian Hack committed
553
554
555

	be_node_set_reg_class(irn, 0, cls_frame);
	be_node_set_reg_class(irn, OUT_POS(0), cls);
Sebastian Hack's avatar
Sebastian Hack committed
556
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
557
}
Sebastian Hack's avatar
Sebastian Hack committed
558

559
ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
Sebastian Hack's avatar
Sebastian Hack committed
560
561
562
563
{
	ir_node *irn;
	ir_node *in[1];

564
	irn = new_ir_node(NULL, irg, bl, op_be_RegParams, mode_T, 0, in);
Sebastian Hack's avatar
Sebastian Hack committed
565
	init_node_attr(irn, n_outs);
Sebastian Hack's avatar
Sebastian Hack committed
566
567
568
	return irn;
}

569
570
571
572
573
574
575
576
577
ir_node *be_new_FrameLoad(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
						  ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, entity *ent)
{
	be_frame_attr_t *a;
	ir_node *irn;
	ir_node *in[2];

	in[0]  = mem;
	in[1]  = frame;
578
	irn    = new_ir_node(NULL, irg, bl, op_be_FrameLoad, mode_T, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
579
	a      = init_node_attr(irn, 3);
580
581
582
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 1, cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
583
	be_node_set_reg_class(irn, OUT_POS(pn_Load_res), cls_data);
584
585
586
587
588
589
590
591
592
593
594
595
596
	return irn;
}

ir_node *be_new_FrameStore(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
						   ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_node *data, entity *ent)
{
	be_frame_attr_t *a;
	ir_node *irn;
	ir_node *in[3];

	in[0]  = mem;
	in[1]  = frame;
	in[2]  = data;
597
	irn    = new_ir_node(NULL, irg, bl, op_be_FrameStore, mode_T, 3, in);
Sebastian Hack's avatar
Sebastian Hack committed
598
	a      = init_node_attr(irn, 3);
599
600
601
602
603
604
605
606
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 1, cls_frame);
	be_node_set_reg_class(irn, 2, cls_data);
	return irn;
}

ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, entity *ent)
Sebastian Hack's avatar
Sebastian Hack committed
607
{
608
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
609
610
611
	ir_node *irn;
	ir_node *in[1];

612
	in[0]  = frame;
613
	irn    = new_ir_node(NULL, irg, bl, op_be_FrameAddr, get_irn_mode(frame), 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
614
	a      = init_node_attr(irn, 1);
615
616
617
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 0, cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
618
	be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
Michael Beck's avatar
Michael Beck committed
619
620

	return optimize_node(irn);
Sebastian Hack's avatar
Sebastian Hack committed
621
622
}

Sebastian Hack's avatar
Sebastian Hack committed
623
624
625
626
627
628
629
630
ir_node *be_new_CopyKeep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, int n, ir_node *in_keep[], ir_mode *mode)
{
	ir_node *irn;
	ir_node **in = (ir_node **) alloca((n + 1) * sizeof(in[0]));

	in[0] = src;
	memcpy(&in[1], in_keep, n * sizeof(in[0]));
	irn   = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, n + 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
631
	init_node_attr(irn, n + 1);
Sebastian Hack's avatar
Sebastian Hack committed
632
633
634
635
636
637
638
639
640
641
642
643
644
645
	be_node_set_reg_class(irn, OUT_POS(0), cls);
	be_node_set_reg_class(irn, 0, cls);

	return irn;
}

ir_node *be_new_CopyKeep_single(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, ir_node *keep, ir_mode *mode)
{
	ir_node *in[1];

	in[0] = keep;
	return be_new_CopyKeep(cls, irg, bl, src, 1, in, mode);
}

646
647
648
649
650
651
652
653
ir_node *be_get_CopyKeep_op(const ir_node *cpy) {
	return get_irn_n(cpy, be_pos_CopyKeep_op);
}

void be_set_CopyKeep_op(ir_node *cpy, ir_node *op) {
	set_irn_n(cpy, be_pos_CopyKeep_op, op);
}

654
ir_node *be_new_Barrier(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
Sebastian Hack's avatar
Sebastian Hack committed
655
656
657
{
	ir_node *irn;

658
	irn = new_ir_node(NULL, irg, bl, op_be_Barrier, mode_T, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
659
660
661
662
	init_node_attr(irn, n);
	return irn;
}

Sebastian Hack's avatar
Sebastian Hack committed
663
664
665
int be_is_Spill         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Spill          ; }
int be_is_Reload        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Reload         ; }
int be_is_Copy          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Copy           ; }
Sebastian Hack's avatar
Sebastian Hack committed
666
int be_is_CopyKeep      (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_CopyKeep       ; }
Sebastian Hack's avatar
Sebastian Hack committed
667
668
669
670
671
int be_is_Perm          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Perm           ; }
int be_is_Keep          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Keep           ; }
int be_is_Call          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Call           ; }
int be_is_Return        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Return         ; }
int be_is_IncSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_IncSP          ; }
Sebastian Hack's avatar
Sebastian Hack committed
672
int be_is_SetSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SetSP          ; }
Sebastian Hack's avatar
Sebastian Hack committed
673
int be_is_AddSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_AddSP          ; }
Sebastian Hack's avatar
Sebastian Hack committed
674
675
int be_is_RegParams     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_RegParams      ; }
int be_is_StackParam    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_StackParam     ; }
676
677
678
int be_is_FrameAddr     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameAddr      ; }
int be_is_FrameLoad     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameLoad      ; }
int be_is_FrameStore    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameStore     ; }
679
int be_is_Barrier       (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Barrier        ; }
680
681
682
683
684
685

int be_has_frame_entity(const ir_node *irn)
{
	switch(be_get_irn_opcode(irn)) {
	case beo_StackParam:
	case beo_Spill:
686
	case beo_Reload:
687
688
689
690
	case beo_FrameStore:
	case beo_FrameLoad:
	case beo_FrameAddr:
		return 1;
691
692
	default:
		return 0;
693
694
695
	}
}

696
entity *be_get_frame_entity(const ir_node *irn)
697
698
699
700
701
702
703
{
	if(be_has_frame_entity(irn)) {
		be_frame_attr_t *a = get_irn_attr(irn);
		return a->ent;
	}
	return NULL;
}
Sebastian Hack's avatar
Sebastian Hack committed
704

Sebastian Hack's avatar
Sebastian Hack committed
705
static void be_limited(void *data, bitset_t *bs)
Sebastian Hack's avatar
Sebastian Hack committed
706
{
Sebastian Hack's avatar
Sebastian Hack committed
707
708
	be_req_t *req = data;

Sebastian Hack's avatar
Sebastian Hack committed
709
710
711
712
713
714
715
716
717
718
719
720
	switch(req->kind) {
	case be_req_kind_negate_old_limited:
	case be_req_kind_old_limited:
		req->x.old_limited.old_limited(req->x.old_limited.old_limited_env, bs);
		if(req->kind == be_req_kind_negate_old_limited)
			bitset_flip_all(bs);
		break;
	case be_req_kind_single_reg:
		bitset_clear_all(bs);
		bitset_set(bs, req->x.single_reg->index);
		break;
	}
Sebastian Hack's avatar
Sebastian Hack committed
721
722
}

Sebastian Hack's avatar
Sebastian Hack committed
723
static INLINE be_req_t *get_req(ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
724
{
Michael Beck's avatar
Michael Beck committed
725
	int idx           = pos < 0 ? -(pos + 1) : pos;
Sebastian Hack's avatar
Sebastian Hack committed
726
727
728
729
730
731
	be_node_attr_t *a = get_irn_attr(irn);
	be_reg_data_t *rd = &a->reg_data[idx];
	be_req_t       *r = pos < 0 ? &rd->req : &rd->in_req;

	assert(is_be_node(irn));
	assert(!(pos >= 0) || pos < get_irn_arity(irn));
Sebastian Hack's avatar
Sebastian Hack committed
732
	assert(!(pos < 0)  || -(pos + 1) <= a->max_reg_data);
Sebastian Hack's avatar
Sebastian Hack committed
733

Sebastian Hack's avatar
Sebastian Hack committed
734
735
736
737
738
739
740
	return r;
}

void be_set_constr_single_reg(ir_node *irn, int pos, const arch_register_t *reg)
{
	be_req_t *r = get_req(irn, pos);

Sebastian Hack's avatar
Sebastian Hack committed
741
742
743
744
745
746
747
748
	r->kind            = be_req_kind_single_reg;
	r->x.single_reg    = reg;
	r->req.limited     = be_limited;
	r->req.limited_env = r;
	r->req.type        = arch_register_req_type_limited;
	r->req.cls         = reg->reg_class;
}

749
750
void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req)
{
Sebastian Hack's avatar
Sebastian Hack committed
751
	be_req_t *r = get_req(irn, pos);
752
753
754
755
756
757
758
759
760
761
762
763
764

	assert(arch_register_req_is(req, limited));

	r->kind            = be_req_kind_old_limited;
	r->req.limited     = be_limited;
	r->req.limited_env = r;
	r->req.type        = arch_register_req_type_limited;
	r->req.cls         = req->cls;

	r->x.old_limited.old_limited     = req->limited;
	r->x.old_limited.old_limited_env = req->limited_env;
}

Sebastian Hack's avatar
Sebastian Hack committed
765
766
767
768
769
770
771
772
773
774
void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
{
	be_req_t *r = get_req(irn, pos);
	r->flags = flags;
}

void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
{
	be_req_t *r = get_req(irn, pos);
	r->req.cls = cls;
Sebastian Hack's avatar
Sebastian Hack committed
775
776
	if(r->req.type == arch_register_req_type_none)
		r->req.type = arch_register_req_type_normal;
Sebastian Hack's avatar
Sebastian Hack committed
777
778
}

779
780
781
782
783
784
void be_node_set_req_type(ir_node *irn, int pos, arch_register_req_type_t type)
{
	be_req_t *r = get_req(irn, pos);
	r->req.type = type;
}

Michael Beck's avatar
BugFix:    
Michael Beck committed
785
786
787
788
789
ir_node *be_get_IncSP_pred(ir_node *irn) {
	assert(be_is_IncSP(irn));
	return get_irn_n(irn, 0);
}

790
void be_set_IncSP_pred(ir_node *incsp, ir_node *pred) {
791
792
793
794
	assert(be_is_IncSP(incsp));
	set_irn_n(incsp, 0, pred);
}

Michael Beck's avatar
Michael Beck committed
795
796
797
798
799
ir_node *be_get_IncSP_mem(ir_node *irn) {
	assert(be_is_IncSP(irn));
	return get_irn_n(irn, 1);
}

Sebastian Hack's avatar
Sebastian Hack committed
800
801
802
803
804
805
void be_set_IncSP_offset(ir_node *irn, unsigned offset)
{
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	a->offset = offset;
}
806

807
unsigned be_get_IncSP_offset(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
808
{
Sebastian Hack's avatar
Sebastian Hack committed
809
810
811
812
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->offset;
}
Sebastian Hack's avatar
Sebastian Hack committed
813

Sebastian Hack's avatar
Sebastian Hack committed
814
815
816
817
818
void be_set_IncSP_direction(ir_node *irn, be_stack_dir_t dir)
{
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	a->dir = dir;
Sebastian Hack's avatar
Sebastian Hack committed
819
820
}

821
be_stack_dir_t be_get_IncSP_direction(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
822
{
Sebastian Hack's avatar
Sebastian Hack committed
823
824
825
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->dir;
Sebastian Hack's avatar
Sebastian Hack committed
826
827
}

828
void be_set_Spill_entity(ir_node *irn, entity *ent)
829
{
Sebastian Hack's avatar
Sebastian Hack committed
830
831
	be_spill_attr_t *a = get_irn_attr(irn);
	assert(be_is_Spill(irn));
832
	a->frame_attr.ent = ent;
833
834
}

835
836
837
838
839
840
841
void be_set_Spill_context(ir_node *irn, ir_node *ctx)
{
	be_spill_attr_t *a = get_irn_attr(irn);
	assert(be_is_Spill(irn));
	a->spill_ctx = ctx;
}

842
843
static ir_node *find_a_spill_walker(ir_node *irn, unsigned visited_nr)
{
844
845
846
	unsigned nr = get_irn_visited(irn);

	set_irn_visited(irn, visited_nr);
847

848
849
850
	if(is_Phi(irn)) {
		int i, n;
		if(nr < visited_nr) {
851
852
853
854
855
856
857
858
			for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
				ir_node *n = find_a_spill_walker(get_irn_n(irn, i), visited_nr);
				if(n != NULL)
					return n;
			}
		}
	}

859
860
861
	else if(be_get_irn_opcode(irn) == beo_Spill)
		return irn;

862
863
864
	return NULL;
}

Sebastian Hack's avatar
Sebastian Hack committed
865
866
867
ir_node *be_get_Spill_context(const ir_node *irn) {
	const be_spill_attr_t *a = get_irn_attr(irn);
	assert(be_is_Spill(irn));
868
869
870
	return a->spill_ctx;
}

871
872
873
874
875
876
/**
 * Finds a spill for a reload.
 * If the reload is directly using the spill, this is simple,
 * else we perform DFS from the reload (over all PhiMs) and return
 * the first spill node we find.
 */
877
static INLINE ir_node *find_a_spill(const ir_node *irn)
878
879
880
881
{
	ir_graph *irg       = get_irn_irg(irn);
	unsigned visited_nr = get_irg_visited(irg) + 1;

Sebastian Hack's avatar
Sebastian Hack committed
882
	assert(be_is_Reload(irn));
883
	set_irg_visited(irg, visited_nr);
Sebastian Hack's avatar
Sebastian Hack committed
884
	return find_a_spill_walker(be_get_Reload_mem(irn), visited_nr);
885
886
}

887
entity *be_get_spill_entity(const ir_node *irn)
888
{
Sebastian Hack's avatar
Sebastian Hack committed
889
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
890
	case beo_Reload:
891
892
893
894
		{
			ir_node *spill = find_a_spill(irn);
			return be_get_spill_entity(spill);
		}
Sebastian Hack's avatar
Sebastian Hack committed
895
896
897
	case beo_Spill:
		{
			be_spill_attr_t *a = get_irn_attr(irn);
898
			return a->frame_attr.ent;
Sebastian Hack's avatar
Sebastian Hack committed
899
		}
900
	default:
Sebastian Hack's avatar
Sebastian Hack committed
901
		assert(0 && "Must give spill/reload node");
902
		break;
903
904
	}

905
	return NULL;
Sebastian Hack's avatar
Sebastian Hack committed
906
907
}

Sebastian Hack's avatar
Sebastian Hack committed
908
static void link_reload_walker(ir_node *irn, void *data)
909
{
Sebastian Hack's avatar
Sebastian Hack committed
910
	ir_node **root = (ir_node **) data;
911
	if(be_is_Reload(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
912
913
		set_irn_link(irn, *root);
		*root = irn;
914
915
916
917
918
	}
}

void be_copy_entities_to_reloads(ir_graph *irg)
{
Sebastian Hack's avatar
Sebastian Hack committed
919
920
921
922
923
924
925
926
927
	ir_node *irn = NULL;
	irg_walk_graph(irg, link_reload_walker, NULL, (void *) &irn);

	while(irn) {
		be_frame_attr_t *a = get_irn_attr(irn);
		entity *ent        = be_get_spill_entity(irn);
		a->ent = ent;
		irn    = get_irn_link(irn);
	}
928
929
}

Sebastian Hack's avatar
Sebastian Hack committed
930
ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn, ir_node *ctx)
Sebastian Hack's avatar
Sebastian Hack committed
931
{
932
933
934
935
	ir_node *bl     = get_nodes_block(irn);
	ir_graph *irg   = get_irn_irg(bl);
	ir_node *frame  = get_irg_frame(irg);
	ir_node *insert = bl;
Sebastian Hack's avatar
Sebastian Hack committed
936
	ir_node *spill;
Sebastian Hack's avatar
Sebastian Hack committed
937

Sebastian Hack's avatar
Sebastian Hack committed
938
939
940
941
	const arch_register_class_t *cls       = arch_get_irn_reg_class(arch_env, irn, -1);
	const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);

	spill = be_new_Spill(cls, cls_frame, irg, bl, frame, irn, ctx);
942
	return spill;
Sebastian Hack's avatar
Sebastian Hack committed
943

944
#if 0
Sebastian Hack's avatar
Sebastian Hack committed
945
946
947
	/*
	 * search the right insertion point. a spill of a phi cannot be put
	 * directly after the phi, if there are some phis behind the one which
Sebastian Hack's avatar
Sebastian Hack committed
948
949
	 * is spilled. Also, a spill of a Proj must be after all Projs of the
	 * same tuple node.
950
	 *
Sebastian Hack's avatar
Sebastian Hack committed
951
952
	 * Here's one special case:
	 * If the spill is in the start block, the spill must be after the frame
953
954
	 * pointer is set up. This is done by setting insert to the end of the block
	 * which is its default initialization (see above).
Sebastian Hack's avatar
Sebastian Hack committed
955
	 */
956
957

	insert = sched_next(irn);
958
	if(insert != bl && bl == get_irg_start_block(irg) && sched_get_time_step(frame) >= sched_get_time_step(insert))
959
960
961
962
		insert = sched_next(frame);

	while((is_Phi(insert) || is_Proj(insert)) && !sched_is_end(insert))
		insert = sched_next(insert);
Sebastian Hack's avatar
Sebastian Hack committed
963

Sebastian Hack's avatar
Sebastian Hack committed
964
	sched_add_before(insert, spill);
Christian Würdig's avatar
Christian Würdig committed
965
	return spill;
966
#endif
Sebastian Hack's avatar
Sebastian Hack committed
967
968
}

969
ir_node *be_reload(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *insert, ir_mode *mode, ir_node *spill)
Sebastian Hack's avatar
Sebastian Hack committed
970
971
972
{
	ir_node *reload;

973
	ir_node *bl    = is_Block(insert) ? insert : get_nodes_block(insert);
Sebastian Hack's avatar
Sebastian Hack committed
974
975
976
	ir_graph *irg  = get_irn_irg(bl);
	ir_node *frame = get_irg_frame(irg);
	const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
Sebastian Hack's avatar
Sebastian Hack committed
977

Sebastian Hack's avatar
Sebastian Hack committed
978
	assert(be_is_Spill(spill) || (is_Phi(spill) && get_irn_mode(spill) == mode_M));
Sebastian Hack's avatar
Sebastian Hack committed
979

Sebastian Hack's avatar
Sebastian Hack committed
980
	reload = be_new_Reload(cls, cls_frame, irg, bl, frame, spill, mode);
Sebastian Hack's avatar
Sebastian Hack committed
981

982
983
984
985
986
987
988
989
	if(is_Block(insert)) {
		insert = sched_skip(insert, 0, sched_skip_cf_predicator, (void *) arch_env);
		sched_add_after(insert, reload);
	}

	else
		sched_add_before(insert, reload);

Christian Würdig's avatar
Christian Würdig committed
990
	return reload;
Sebastian Hack's avatar
Sebastian Hack committed
991
}
Sebastian Hack's avatar
Sebastian Hack committed
992

Sebastian Hack's avatar
Sebastian Hack committed
993
994
995
996
997
998
999
1000
1001
1002
1003
/*
  ____              ____
 |  _ \ ___  __ _  |  _ \ ___  __ _ ___
 | |_) / _ \/ _` | | |_) / _ \/ _` / __|
 |  _ <  __/ (_| | |  _ <  __/ (_| \__ \
 |_| \_\___|\__, | |_| \_\___|\__, |___/
            |___/                |_|

*/


Sebastian Hack's avatar