il1_anal.c 3.8 KB

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