aboutsummaryrefslogtreecommitdiff
path: root/reassoc.c
blob: 25d88ea34c146772a81add747588c7733d7a5006 (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
#include "all.h"

static void
ireassoc(Fn *fn, Blk *b, Ins *i, uint *pnim, InsMov **pim)
{
	Blk *b2;
	Tmp *t;
	Use *u;
	int64_t v;
	int x;

	assert(b->ins <= i && i < &b->ins[b->nins]);
	if (!iscmp(i->op, &x, &x))
	if (!iskladdcon(fn, i, &v))
		return;

	assert(rtype(i->to) == RTmp);
	t = &fn->tmp[i->to.val];
	for (u = t->use; u < &t->use[t->nuse]; u++) {
		if (u->type == UPhi)
			continue;
		if (u->type == UIns)
		if (INRANGE(u->u.ins->op, Oarg, Ocall))
			continue;
		b2 = fn->rpo[u->bid];
		vgrow(pim, ++(*pnim));
		(*pim)[(*pnim)-1] = (InsMov){
			.from = {.bid = b->id, .insn = i-b->ins},
			.to = {
				.bid = u->bid,
				.insn = u->type == UJmp ? b2->nins : u->u.ins-b2->ins
			}};
	}
}

static void
trealloc(Fn *fn, Blk *b, Ins *i)
{
	Ins *i2;
	Ref r;

	assert(b->ins <= i && i < &b->ins[b->nins]);
	r = newtmp("rea", i->cls, fn);
	if (i < &b->ins[b->nins-1]) {
		i2 = i+1;
		/* special case of both args of target instruction reassociated */
		if (!req(i->to, i2->arg[0]) && !req(i->to, i2->arg[1])) {
			assert(i < &b->ins[b->nins-2]);
			i2 = i+2;
		}
		assert(req(i->to, i2->arg[0]) || req(i->to, i2->arg[1]));
		if (req(i->to, i2->arg[0]))
			i2->arg[0] = r;
		if (req(i->to, i2->arg[1]))
			i2->arg[1] = r;
	} else {
		assert(req(i->to, b->jmp.arg));
		b->jmp.arg = r;
	}
	i->to = r;
}

/* Redistribute trivial ops to point of use. */
/* Reduces register pressure. */
/* needs rpo, use; breaks use */
void
reassoc(Fn *fn)
{
	Blk *b;
	Ins *i;
	InsMov *im;
	uint n, nim;

	nim = 0;
	im = vnew(nim, sizeof im[0], PHeap);

	/* identify trivial ins */
	for (b = fn->start; b; b = b->link) {
		for (i = b->ins; i < &b->ins[b->nins]; i++)
			ireassoc(fn, b, i, &nim, &im);
	}

	/* duplicate trivial ins */
	movins(fn, im, nim, 0/*!del*/);

	/* create new tmps for dups */
	for (n = 0; n < nim; n++) {
		b = fn->rpo[im[n].to.bid];
		i = &b->ins[im[n].to.insn];
		trealloc(fn, b, i);
	}

	/* delete (now) unused ins */
	filluse(fn);
	nopunused(fn);

	if (debug['G']) {
		fprintf(stderr, "\n> After Reassociation:\n");
		printfn(fn, stderr);
	}
}