il1_anal.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. /* I N L I N E S U B S T I T U T I O N
  7. *
  8. * I L 1 _ A N A L . C
  9. */
  10. #include <stdio.h>
  11. #include <em_mnem.h>
  12. #include <em_pseu.h>
  13. #include "../share/types.h"
  14. #include "il.h"
  15. #include "../share/debug.h"
  16. #include "../share/alloc.h"
  17. #include "../share/global.h"
  18. #include "../share/lset.h"
  19. #include "../share/aux.h"
  20. #include "il1_aux.h"
  21. #include "il1_formal.h"
  22. #include "il1_cal.h"
  23. #include "il1_anal.h"
  24. #include "il_aux.h"
  25. #include "../share/put.h"
  26. #define ENVIRON(p) (p->p_flags1 & (byte) PF_ENVIRON)
  27. #define RETURN_BLOCK(b) (Lnrelems(b->b_succ) == 0)
  28. #define LAST_BLOCK(b) (b->b_next == (bblock_p) 0)
  29. /* Daisy chain recursion not yet accounted for: */
  30. #define RECURSIVE(p) (Cis_elem(p->p_id,p->p_calling))
  31. /*
  32. #define CALLS_UNKNOWN(p) (p->p_flags1 & (byte) PF_CALUNKNOWN)
  33. */
  34. #define CALLS_UNKNOWN(p) (FALSE)
  35. apriori(proctab)
  36. proc_p proctab;
  37. {
  38. /* For every procedure, see if we can determine
  39. * from the information provided by the previous
  40. * phases of the optimizer that it cannot or should not
  41. * be expanded in line. This will reduce the length
  42. * of the call list.
  43. */
  44. register proc_p p;
  45. for (p = proctab; p != (proc_p) 0; p = p->p_next) {
  46. if (!BODY_KNOWN(p) ||
  47. ENVIRON(p) || RECURSIVE(p) ||
  48. PARAMS_UNKNOWN(p) || MANY_LOCALS(p) ||
  49. IS_ENTERED_WITH_GTO(p)) {
  50. UNSUITABLE(p);
  51. #ifdef VERBOSE
  52. if (BODY_KNOWN(p)) {
  53. if (ENVIRON(p)) Senv++;
  54. if (RECURSIVE(p)) Srecursive++;
  55. if (MANY_LOCALS(p)) Slocals++;
  56. }
  57. #endif
  58. }
  59. }
  60. }
  61. STATIC check_labels(p,arglist)
  62. proc_p p;
  63. arg_p arglist;
  64. {
  65. /* Check if any of the arguments contains an instruction
  66. * label; if so, make p unsuitable.
  67. */
  68. arg_p arg;
  69. for (arg = arglist; arg != (arg_p) 0; arg = arg->a_next) {
  70. if (arg->a_type == ARGINSTRLAB) {
  71. UNSUITABLE(p);
  72. #ifdef VERBOSE
  73. Sinstrlab++;
  74. #endif
  75. break;
  76. }
  77. }
  78. }
  79. STATIC anal_instr(p,b,cf)
  80. proc_p p;
  81. bblock_p b;
  82. FILE *cf;
  83. {
  84. /* Analyze the instructions of block b
  85. * within procedure p.
  86. * See which parameters are used, changed
  87. * or have their address taken. Recognize
  88. * the actual parameter expressions of
  89. * the CAL instructions.
  90. */
  91. register line_p l;
  92. for (l = b->b_start; l != (line_p) 0; l = l->l_next) {
  93. switch(INSTR(l)) {
  94. case op_cal:
  95. anal_cal(p,l,b,cf);
  96. break;
  97. case op_stl:
  98. case op_inl:
  99. case op_del:
  100. case op_zrl:
  101. formal(p,b,off_set(l),SINGLE,CHANGE);
  102. /* see if the local is a parameter.
  103. * If so, it is a one-word parameter
  104. * that is stored into.
  105. */
  106. break;
  107. case op_sdl:
  108. formal(p,b,off_set(l),DOUBLE,CHANGE);
  109. break;
  110. case op_lol:
  111. formal(p,b,off_set(l),SINGLE,USE);
  112. break;
  113. case op_ldl:
  114. formal(p,b,off_set(l),DOUBLE,USE);
  115. break;
  116. case op_sil:
  117. case op_lil:
  118. formal(p,b,off_set(l),POINTER,USE);
  119. break;
  120. case op_lal:
  121. formal(p,b,off_set(l),UNKNOWN,ADDRESS);
  122. break;
  123. case ps_rom:
  124. case ps_con:
  125. case ps_bss:
  126. case ps_hol:
  127. check_labels(p,ARG(l));
  128. break;
  129. case op_nop: /* volatile */
  130. UNSUITABLE(p);
  131. break;
  132. }
  133. }
  134. }
  135. anal_proc(p,cf,ccf)
  136. proc_p p;
  137. FILE *cf,*ccf;
  138. {
  139. /* Analyze a procedure; use information
  140. * stored in its basic blocks or in
  141. * its instructions.
  142. */
  143. register bblock_p b;
  144. bool fallthrough = TRUE;
  145. cchead = (calcnt_p) 0;
  146. for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
  147. if (RETURN_BLOCK(b) && !LAST_BLOCK(b)) {
  148. fallthrough = FALSE;
  149. /* p contains a RET instruction somewhere
  150. * in the middle of its code.
  151. */
  152. }
  153. anal_instr(p,b,cf); /* analyze instructions */
  154. }
  155. if (fallthrough) {
  156. p->p_flags2 |= PF_FALLTHROUGH;
  157. }
  158. rem_indir_acc(p);
  159. /* don't expand formal that may be accessed indirectly */
  160. p->P_CCADDR = putcc(cchead,ccf);
  161. /* write calcnt info and remember disk address */
  162. remcc(cchead);
  163. }