liveness.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * Register - track pseudo usage, maybe eventually try to do register
  3. * allocation.
  4. *
  5. * Copyright (C) 2004 Linus Torvalds
  6. */
  7. #include <assert.h>
  8. #include "liveness.h"
  9. #include "parse.h"
  10. #include "expression.h"
  11. #include "linearize.h"
  12. #include "flow.h"
  13. static void phi_defines(struct instruction * phi_node, pseudo_t target,
  14. void (*defines)(struct basic_block *, pseudo_t))
  15. {
  16. pseudo_t phi;
  17. FOR_EACH_PTR(phi_node->phi_list, phi) {
  18. struct instruction *def;
  19. if (phi == VOID)
  20. continue;
  21. def = phi->def;
  22. if (!def || !def->bb)
  23. continue;
  24. defines(def->bb, target);
  25. } END_FOR_EACH_PTR(phi);
  26. }
  27. static void asm_liveness(struct basic_block *bb, struct instruction *insn,
  28. void (*def)(struct basic_block *, pseudo_t),
  29. void (*use)(struct basic_block *, pseudo_t))
  30. {
  31. struct asm_constraint *entry;
  32. FOR_EACH_PTR(insn->asm_rules->inputs, entry) {
  33. use(bb, entry->pseudo);
  34. } END_FOR_EACH_PTR(entry);
  35. FOR_EACH_PTR(insn->asm_rules->outputs, entry) {
  36. if (entry->is_memory)
  37. use(bb, entry->pseudo);
  38. else
  39. def(bb, entry->pseudo);
  40. } END_FOR_EACH_PTR(entry);
  41. }
  42. static void track_instruction_usage(struct basic_block *bb, struct instruction *insn,
  43. void (*def)(struct basic_block *, pseudo_t),
  44. void (*use)(struct basic_block *, pseudo_t))
  45. {
  46. pseudo_t pseudo;
  47. #define USES(x) use(bb, insn->x)
  48. #define DEFINES(x) def(bb, insn->x)
  49. switch (insn->opcode) {
  50. case OP_RET:
  51. case OP_COMPUTEDGOTO:
  52. USES(src);
  53. break;
  54. case OP_CBR:
  55. case OP_SWITCH:
  56. USES(cond);
  57. break;
  58. /* Binary */
  59. case OP_BINARY ... OP_BINARY_END:
  60. case OP_FPCMP ... OP_FPCMP_END:
  61. case OP_BINCMP ... OP_BINCMP_END:
  62. USES(src1); USES(src2); DEFINES(target);
  63. break;
  64. /* Uni */
  65. case OP_UNOP ... OP_UNOP_END:
  66. case OP_SYMADDR:
  67. USES(src1); DEFINES(target);
  68. break;
  69. case OP_SEL:
  70. USES(src1); USES(src2); USES(src3); DEFINES(target);
  71. break;
  72. /* Memory */
  73. case OP_LOAD:
  74. USES(src); DEFINES(target);
  75. break;
  76. case OP_STORE:
  77. USES(src); USES(target);
  78. break;
  79. case OP_SETVAL:
  80. case OP_SETFVAL:
  81. DEFINES(target);
  82. break;
  83. /* Other */
  84. case OP_PHI:
  85. /* Phi-nodes are "backwards" nodes. Their def doesn't matter */
  86. phi_defines(insn, insn->target, def);
  87. break;
  88. case OP_PHISOURCE:
  89. /*
  90. * We don't care about the phi-source define, they get set
  91. * up and expanded by the OP_PHI
  92. */
  93. USES(phi_src);
  94. break;
  95. case OP_CALL:
  96. USES(func);
  97. if (insn->target != VOID)
  98. DEFINES(target);
  99. FOR_EACH_PTR(insn->arguments, pseudo) {
  100. use(bb, pseudo);
  101. } END_FOR_EACH_PTR(pseudo);
  102. break;
  103. case OP_SLICE:
  104. USES(base); DEFINES(target);
  105. break;
  106. case OP_ASM:
  107. asm_liveness(bb, insn, def, use);
  108. break;
  109. case OP_RANGE:
  110. USES(src1); USES(src2); USES(src3);
  111. break;
  112. case OP_BADOP:
  113. case OP_NOP:
  114. case OP_CONTEXT:
  115. break;
  116. }
  117. }
  118. static int liveness_changed;
  119. static void add_pseudo_exclusive(struct pseudo_list **list, pseudo_t pseudo)
  120. {
  121. if (!pseudo_in_list(*list, pseudo)) {
  122. liveness_changed = 1;
  123. add_pseudo(list, pseudo);
  124. }
  125. }
  126. static inline int trackable_pseudo(pseudo_t pseudo)
  127. {
  128. return pseudo && (pseudo->type == PSEUDO_REG || pseudo->type == PSEUDO_ARG);
  129. }
  130. static void insn_uses(struct basic_block *bb, pseudo_t pseudo)
  131. {
  132. if (trackable_pseudo(pseudo)) {
  133. struct instruction *def = pseudo->def;
  134. if (pseudo->type != PSEUDO_REG || def->bb != bb || def->opcode == OP_PHI)
  135. add_pseudo_exclusive(&bb->needs, pseudo);
  136. }
  137. }
  138. static void insn_defines(struct basic_block *bb, pseudo_t pseudo)
  139. {
  140. assert(trackable_pseudo(pseudo));
  141. add_pseudo(&bb->defines, pseudo);
  142. }
  143. static void track_bb_liveness(struct basic_block *bb)
  144. {
  145. pseudo_t needs;
  146. FOR_EACH_PTR(bb->needs, needs) {
  147. struct basic_block *parent;
  148. FOR_EACH_PTR(bb->parents, parent) {
  149. if (!pseudo_in_list(parent->defines, needs)) {
  150. add_pseudo_exclusive(&parent->needs, needs);
  151. }
  152. } END_FOR_EACH_PTR(parent);
  153. } END_FOR_EACH_PTR(needs);
  154. }
  155. /*
  156. * We need to clear the liveness information if we
  157. * are going to re-run it.
  158. */
  159. void clear_liveness(struct entrypoint *ep)
  160. {
  161. struct basic_block *bb;
  162. FOR_EACH_PTR(ep->bbs, bb) {
  163. free_ptr_list(&bb->needs);
  164. free_ptr_list(&bb->defines);
  165. } END_FOR_EACH_PTR(bb);
  166. }
  167. /*
  168. * Track inter-bb pseudo liveness. The intra-bb case
  169. * is purely local information.
  170. */
  171. void track_pseudo_liveness(struct entrypoint *ep)
  172. {
  173. struct basic_block *bb;
  174. /* Add all the bb pseudo usage */
  175. FOR_EACH_PTR(ep->bbs, bb) {
  176. struct instruction *insn;
  177. FOR_EACH_PTR(bb->insns, insn) {
  178. if (!insn->bb)
  179. continue;
  180. assert(insn->bb == bb);
  181. track_instruction_usage(bb, insn, insn_defines, insn_uses);
  182. } END_FOR_EACH_PTR(insn);
  183. } END_FOR_EACH_PTR(bb);
  184. /* Calculate liveness.. */
  185. do {
  186. liveness_changed = 0;
  187. FOR_EACH_PTR_REVERSE(ep->bbs, bb) {
  188. track_bb_liveness(bb);
  189. } END_FOR_EACH_PTR_REVERSE(bb);
  190. } while (liveness_changed);
  191. /* Remove the pseudos from the "defines" list that are used internally */
  192. FOR_EACH_PTR(ep->bbs, bb) {
  193. pseudo_t def;
  194. FOR_EACH_PTR(bb->defines, def) {
  195. struct basic_block *child;
  196. FOR_EACH_PTR(bb->children, child) {
  197. if (pseudo_in_list(child->needs, def))
  198. goto is_used;
  199. } END_FOR_EACH_PTR(child);
  200. DELETE_CURRENT_PTR(def);
  201. is_used:
  202. ;
  203. } END_FOR_EACH_PTR(def);
  204. PACK_PTR_LIST(&bb->defines);
  205. } END_FOR_EACH_PTR(bb);
  206. }
  207. static void merge_pseudo_list(struct pseudo_list *src, struct pseudo_list **dest)
  208. {
  209. pseudo_t pseudo;
  210. FOR_EACH_PTR(src, pseudo) {
  211. add_pseudo_exclusive(dest, pseudo);
  212. } END_FOR_EACH_PTR(pseudo);
  213. }
  214. static void track_phi_uses(struct instruction *insn)
  215. {
  216. pseudo_t phi;
  217. FOR_EACH_PTR(insn->phi_list, phi) {
  218. struct instruction *def;
  219. if (phi == VOID || !phi->def)
  220. continue;
  221. def = phi->def;
  222. assert(def->opcode == OP_PHISOURCE);
  223. add_ptr_list(&def->phi_users, insn);
  224. } END_FOR_EACH_PTR(phi);
  225. }
  226. static void track_bb_phi_uses(struct basic_block *bb)
  227. {
  228. struct instruction *insn;
  229. FOR_EACH_PTR(bb->insns, insn) {
  230. if (insn->bb && insn->opcode == OP_PHI)
  231. track_phi_uses(insn);
  232. } END_FOR_EACH_PTR(insn);
  233. }
  234. static struct pseudo_list **live_list;
  235. static struct pseudo_list *dead_list;
  236. static void death_def(struct basic_block *bb, pseudo_t pseudo)
  237. {
  238. }
  239. static void death_use(struct basic_block *bb, pseudo_t pseudo)
  240. {
  241. if (trackable_pseudo(pseudo) && !pseudo_in_list(*live_list, pseudo)) {
  242. add_pseudo(&dead_list, pseudo);
  243. add_pseudo(live_list, pseudo);
  244. }
  245. }
  246. static void track_pseudo_death_bb(struct basic_block *bb)
  247. {
  248. struct pseudo_list *live = NULL;
  249. struct basic_block *child;
  250. struct instruction *insn;
  251. FOR_EACH_PTR(bb->children, child) {
  252. merge_pseudo_list(child->needs, &live);
  253. } END_FOR_EACH_PTR(child);
  254. live_list = &live;
  255. FOR_EACH_PTR_REVERSE(bb->insns, insn) {
  256. if (!insn->bb)
  257. continue;
  258. dead_list = NULL;
  259. track_instruction_usage(bb, insn, death_def, death_use);
  260. if (dead_list) {
  261. pseudo_t dead;
  262. FOR_EACH_PTR(dead_list, dead) {
  263. struct instruction *deathnote = __alloc_instruction(0);
  264. deathnote->bb = bb;
  265. deathnote->opcode = OP_DEATHNOTE;
  266. deathnote->target = dead;
  267. INSERT_CURRENT(deathnote, insn);
  268. } END_FOR_EACH_PTR(dead);
  269. free_ptr_list(&dead_list);
  270. }
  271. } END_FOR_EACH_PTR_REVERSE(insn);
  272. free_ptr_list(&live);
  273. }
  274. void track_pseudo_death(struct entrypoint *ep)
  275. {
  276. struct basic_block *bb;
  277. FOR_EACH_PTR(ep->bbs, bb) {
  278. track_bb_phi_uses(bb);
  279. } END_FOR_EACH_PTR(bb);
  280. FOR_EACH_PTR(ep->bbs, bb) {
  281. track_pseudo_death_bb(bb);
  282. } END_FOR_EACH_PTR(bb);
  283. }