QBE
mem.c
См. документацию.
1 #include "all.h"
2 
3 /* require use, maintains use counts */
4 void
5 memopt(Fn *fn)
6 {
7  Blk *b;
8  Ins *i, *l;
9  Tmp *t;
10  Use *u, *ue;
11  int s, k;
12 
13  /* promote uniform stack slots to temporaries */
14  b = fn->start;
15  for (i=b->ins; i-b->ins < b->nins; i++) {
16  if (Oalloc > i->op || i->op > Oalloc1)
17  continue;
18  /* specific to NAlign == 3 */
19  assert(rtype(i->to) == RTmp);
20  t = &fn->tmp[i->to.val];
21  if (t->ndef != 1)
22  goto Skip;
23  k = -1;
24  s = -1;
25  for (u=t->use; u != &t->use[t->nuse]; u++) {
26  if (u->type != UIns)
27  goto Skip;
28  l = u->u.ins;
29  if (isload(l->op))
30  if (s == -1 || s == loadsz(l)) {
31  s = loadsz(l);
32  continue;
33  }
34  if (isstore(l->op))
35  if (req(i->to, l->arg[1]) && !req(i->to, l->arg[0]))
36  if (s == -1 || s == storesz(l))
37  if (k == -1 || k == optab[l->op].argcls[0][0]) {
38  s = storesz(l);
39  k = optab[l->op].argcls[0][0];
40  continue;
41  }
42  goto Skip;
43  }
44  /* get rid of the alloc and replace uses */
45  *i = (Ins){.op = Onop};
46  t->ndef--;
47  ue = &t->use[t->nuse];
48  for (u=t->use; u!=ue; u++) {
49  l = u->u.ins;
50  if (isstore(l->op)) {
51  l->cls = k;
52  l->op = Ocopy;
53  l->to = l->arg[1];
54  l->arg[1] = R;
55  t->nuse--;
56  t->ndef++;
57  } else {
58  if (k == -1)
59  err("slot %%%s is read but never stored to",
60  fn->tmp[l->arg[0].val].name);
61  /* try to turn loads into copies so we
62  * can eliminate them later */
63  switch(l->op) {
64  case Oloadsw:
65  case Oloaduw:
66  if (k == Kl)
67  goto Extend;
68  case Oload:
69  if (KBASE(k) != KBASE(l->cls))
70  l->op = Ocast;
71  else
72  l->op = Ocopy;
73  break;
74  default:
75  Extend:
76  l->op = Oextsb + (l->op - Oloadsb);
77  break;
78  }
79  }
80  }
81  Skip:;
82  }
83  if (debug['M']) {
84  fprintf(stderr, "\n> After memory optimization:\n");
85  printfn(fn, stderr);
86  }
87 }
int storesz(Ins *)
Definition: load.c:58
Blk * start
Указатель на блок функции, являющийся её входной точкой
Definition: all.h:385
Структура, хранящая информацию об инструкциях.
Definition: all.h:235
Definition: all.h:251
Definition: all.h:275
Definition: all.h:242
#define isstore(o)
Definition: all.h:204
#define KBASE(k)
Definition: all.h:220
Definition: all.h:84
Op optab[NOp]
Массив всех операций.
Definition: parse.c:10
Definition: all.h:196
uint ndef
Количество блоков, в которых есть объявление переменной
Definition: all.h:329
Definition: all.h:214
Definition: all.h:195
Содержит информацию о переменной
Definition: all.h:326
void err(char *,...) __attribute__((noreturn))
Definition: parse.c:134
Tmp * tmp
Массив используемых функцией переменных
Definition: all.h:386
Use * use
Содержит информацию об использовании переменной
Definition: all.h:328
struct Ins Ins
Definition: all.h:19
union Use::@7 u
Непосредственно информация о базовом блоке.
Definition: all.h:254
Definition: all.h:246
void printfn(Fn *, FILE *)
Definition: parse.c:1160
Definition: all.h:283
uint nins
Definition: all.h:257
char name[NString]
Имя переменной
Definition: all.h:327
Ins * ins
Definition: all.h:295
Ref to
Definition: all.h:237
short argcls[2][4]
Definition: all.h:228
Definition: all.h:247
#define isload(o)
Definition: all.h:205
Ins * ins
Definition: all.h:256
Definition: all.h:264
Ref arg[2]
Definition: all.h:238
Definition: all.h:248
uint val
Definition: all.h:80
enum Use::@6 type
#define R
Definition: all.h:92
uint cls
Definition: all.h:239
int loadsz(Ins *)
Definition: load.c:46
Структура, хранящая в себе информацию о функции
Definition: all.h:384
uint nuse
Количество блоков, в которых переменная используется
Definition: all.h:329
void memopt(Fn *fn)
Definition: mem.c:5
uint op
Definition: all.h:236
char debug['Z'+1]
Структура, хранящая информацию об одном "использовании" переменной.
Definition: all.h:286