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);
}
}
|