ud_const.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /* $Id$ */
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. */
  6. /* C O N S T A N T P R O P A G A T I O N */
  7. #include <em_mnem.h>
  8. #include <em_pseu.h>
  9. #include <em_spec.h>
  10. #include "../share/types.h"
  11. #include "ud.h"
  12. #include "../share/debug.h"
  13. #include "../share/global.h"
  14. #include "../share/alloc.h"
  15. #include "../share/lset.h"
  16. #include "../share/cset.h"
  17. #include "../share/def.h"
  18. #include "../share/aux.h"
  19. #include "../share/locals.h"
  20. #include "ud_defs.h"
  21. #include "ud_const.h"
  22. #include "ud_aux.h"
  23. #define IS_REG(v) (locals[TO_LOCAL(v)]->lc_flags & LCF_REG)
  24. #define CALLS_UNKNOWN(p) (p->p_flags1 & (byte) PF_CALUNKNOWN)
  25. bool is_use(line_p l)
  26. {
  27. /* See if 'l' is a use of a variable */
  28. switch(INSTR(l)) {
  29. case op_lde:
  30. case op_ldl:
  31. case op_loe:
  32. case op_lol:
  33. return TRUE;
  34. default:
  35. return FALSE;
  36. }
  37. /* NOTREACHED */
  38. return FALSE;
  39. }
  40. bool value_known(line_p def, offset *val_out)
  41. {
  42. /* See if the value stored by definition 'def'
  43. * is known statically (i.e. is a constant).
  44. */
  45. short sz1, sz2;
  46. offset v = 0;
  47. line_p l;
  48. sz1 = ws;
  49. switch(INSTR(def)) {
  50. case op_inl:
  51. case op_ine:
  52. case op_del:
  53. case op_dee:
  54. return FALSE;
  55. case op_zrl:
  56. case op_zre:
  57. v = (offset) 0;
  58. break;
  59. case op_sdl:
  60. case op_sde:
  61. sz1 += ws;
  62. /* fall through ... */
  63. case op_stl:
  64. case op_ste:
  65. l = PREV(def);
  66. if (l == (line_p) 0) return FALSE;
  67. sz2 = ws;
  68. switch(INSTR(l)) {
  69. case op_zer:
  70. if (SHORT(l) >= sz1) {
  71. v = (offset) 0;
  72. break;
  73. }
  74. return FALSE;
  75. case op_ldc:
  76. sz2 += ws;
  77. /* fall through ...*/
  78. case op_loc:
  79. if (sz1 == sz2) {
  80. v = off_set(l);
  81. break;
  82. }
  83. /* fall through ... */
  84. default:
  85. return FALSE;
  86. }
  87. break;
  88. default:
  89. assert(FALSE);
  90. }
  91. *val_out = v;
  92. return TRUE;
  93. }
  94. bool affected(line_p use, short v, line_p l)
  95. {
  96. /* See if the variable referenced by 'use' may be
  97. * changed by instruction l, which is either a cal, cai or
  98. * an indirect assignment.
  99. */
  100. if (INSTR(l) == op_cal &&
  101. TYPE(use) == OPOBJECT &&
  102. BODY_KNOWN(PROC(l)) &&
  103. !CALLS_UNKNOWN(PROC(l)) &&
  104. !CHANGE_INDIR(PROC(l))) {
  105. return Cis_elem(OBJ(use)->o_id,PROC(l)->p_change->c_ext);
  106. }
  107. return TYPE(use) == OPOBJECT || !IS_REG(v);
  108. }
  109. static void search_backwards(line_p use, short v, bool *found, line_p *def)
  110. {
  111. /* Search backwards in the current basic block,
  112. * starting at 'use', trying to find a definition
  113. * of the variable referenced by 'use', whose variable
  114. * number is v. If the definition found is an
  115. * implicit one, return 0 as def.
  116. */
  117. register line_p l;
  118. for (l = PREV(use); l != (line_p) 0; l = PREV(l)) {
  119. if (does_expl_def(l) && same_var(use,l)) {
  120. *found = TRUE;
  121. *def = l;
  122. return;
  123. }
  124. if (does_impl_def(l) && affected(use,v,l)) {
  125. *found = TRUE;
  126. *def = (line_p) 0;
  127. return;
  128. }
  129. }
  130. *found = FALSE;
  131. }
  132. static short outer_def(cset vdefs, cset in)
  133. {
  134. /* See if there is a unique definition of variable
  135. * v reaching the beginning of block b.
  136. * 'vdefs' is vardefs[v], 'in' is IN(b).
  137. */
  138. short n,defnr = 0;
  139. Cindex i;
  140. for (i = Cfirst(vdefs); i != (Cindex) 0; i = Cnext(i,vdefs)) {
  141. n = Celem(i);
  142. if (Cis_elem(EXPL_TO_DEFNR(n),in)) {
  143. if (defnr != 0) return 0;
  144. /* If there was already a def., there's no unique one */
  145. defnr = n;
  146. }
  147. }
  148. return defnr;
  149. }
  150. line_p unique_def(line_p use, bblock_p b, short *defnr_out)
  151. {
  152. /* See if there is one unique explicit definition
  153. * of the variable used by 'use', that reaches 'use'.
  154. */
  155. short v;
  156. bool found;
  157. line_p def = (line_p) 0;
  158. *defnr_out = 0;
  159. var_nr(use,&v,&found);
  160. if (found) {
  161. /* We do maintain ud-info for this variable.
  162. * See if there is a previous explicit definition
  163. * in the current basic block.
  164. */
  165. search_backwards(use,v,&found,&def);
  166. if (!found && !Cis_elem(IMPLICIT_DEF(v),IN(b))) {
  167. /* See if there is a unique explicit definition
  168. * outside the current block, reaching the
  169. * beginning of the current block.
  170. */
  171. *defnr_out = outer_def(vardefs[v],IN(b));
  172. def = (*defnr_out == 0 ? (line_p) 0 : defs[*defnr_out]);
  173. }
  174. }
  175. return def;
  176. }
  177. void fold_const(line_p l, bblock_p b, offset val)
  178. {
  179. /* Perform the substitutions required for constant folding */
  180. line_p n;
  181. n = int_line(val);
  182. switch(INSTR(l)) {
  183. case op_lol:
  184. case op_loe:
  185. n->l_instr = op_loc;
  186. break;
  187. case op_ldl:
  188. case op_lde:
  189. n->l_instr = op_ldc;
  190. break;
  191. default:
  192. assert (FALSE);
  193. }
  194. repl_line(l,n,b);
  195. }