accept "ret" for functions with a return type
[qbe.git] / mem.c
blobea0bef74dcb218543e3f14f80be7670b0ae6320c
1 #include "all.h"
3 static int
4 loadsz(Ins *l)
6 switch (l->op) {
7 case Oloadsb: case Oloadub: return 1;
8 case Oloadsh: case Oloaduh: return 2;
9 case Oloadsw: case Oloaduw: return 4;
10 case Oload: return KWIDE(l->cls) ? 8 : 4;
12 die("unreachable");
15 static int
16 storesz(Ins *s)
18 switch (s->op) {
19 case Ostoreb: return 1;
20 case Ostoreh: return 2;
21 case Ostorew: case Ostores: return 4;
22 case Ostorel: case Ostored: return 8;
24 die("unreachable");
28 /* require use, maintains use counts */
29 void
30 memopt(Fn *fn)
32 Blk *b;
33 Ins *i, *l;
34 Tmp *t;
35 Use *u, *ue;
36 int s, k;
38 /* promote uniform stack slots to temporaries */
39 b = fn->start;
40 for (i=b->ins; i-b->ins < b->nins; i++) {
41 if (Oalloc > i->op || i->op > Oalloc1)
42 continue;
43 /* specific to NAlign == 3 */
44 assert(rtype(i->to) == RTmp);
45 t = &fn->tmp[i->to.val];
46 if (t->ndef != 1)
47 goto Skip;
48 k = -1;
49 s = -1;
50 for (u=t->use; u != &t->use[t->nuse]; u++) {
51 if (u->type != UIns)
52 goto Skip;
53 l = u->u.ins;
54 if (isload(l->op))
55 if (s == -1 || s == loadsz(l)) {
56 s = loadsz(l);
57 continue;
59 if (isstore(l->op))
60 if (req(i->to, l->arg[1]) && !req(i->to, l->arg[0]))
61 if (s == -1 || s == storesz(l))
62 if (k == -1 || k == opdesc[l->op].argcls[0][0]) {
63 s = storesz(l);
64 k = opdesc[l->op].argcls[0][0];
65 continue;
67 goto Skip;
69 /* get rid of the alloc and replace uses */
70 *i = (Ins){.op = Onop};
71 t->ndef--;
72 ue = &t->use[t->nuse];
73 for (u=t->use; u!=ue; u++) {
74 l = u->u.ins;
75 if (isstore(l->op)) {
76 l->cls = k;
77 l->op = Ocopy;
78 l->to = l->arg[1];
79 l->arg[1] = R;
80 t->nuse--;
81 t->ndef++;
82 } else {
83 if (k == -1)
84 err("slot %%%s is read but never stored to",
85 fn->tmp[l->arg[0].val].name);
86 /* try to turn loads into copies so we
87 * can eliminate them later */
88 switch(l->op) {
89 case Oload:
90 case Oloadsw:
91 case Oloaduw:
92 if (KBASE(k) != KBASE(l->cls))
93 l->op = Ocast;
94 else
95 l->op = Ocopy;
96 break;
97 default:
98 l->op = Oextsb + (l->op - Oloadsb);
99 break;
103 Skip:;
105 if (debug['M']) {
106 fprintf(stderr, "\n> After memory optimization:\n");
107 printfn(fn, stderr);