home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- */
-
- /*
- * Routines for data flow analysis by block and function.
- */
-
- #include "top.h"
-
- /*
- * bprep() - perform initial analysis of individual blocks
- */
- static void
- bprep(bp)
- BLOCK *bp;
- {
- BLOCK *cp;
- INST *ip;
- int ref, set;
-
- for (cp = bp; cp != NULL ;cp = cp->next) {
- ref = set = 0;
- for (ip = cp->first; ip != NULL ;ip = ip->next) {
- ref |= (ip->rref = reg_ref(ip)) & ~set;
- set |= (ip->rset = reg_set(ip));
- }
- cp->rref = ref;
- cp->rset = set;
- }
- }
-
-
- static bool
- scan_ref(bp, reg)
- BLOCK *bp;
- int reg;
- {
- INST *ip;
-
- if (bp == NULL)
- return FALSE;
-
- if (bp->rref & reg)
- return TRUE;
-
- if (bp->rset & reg)
- return FALSE;
-
- if (bp->flags & B_MARK)
- return FALSE;
-
- if (bp->flags & B_RET)
- return FALSE;
-
- bp->flags |= B_MARK;
-
- if (scan_ref(bp->bcond, reg))
- return TRUE;
-
- if (scan_ref(bp->bfall, reg))
- return TRUE;
-
- for (ip = bp->first; ip != NULL ;ip = ip->next) {
- if (ip->opcode == DC && (ip->flags & LENL)) {
- BLOCK *db;
-
- if ((ip->src.astr != NULL) &&
- (db = getsym(ip->src.astr)) != NULL)
- if (scan_ref(db, reg))
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /*
- * is_live(bp, reg) - is 'reg' live at the end of block 'bp'
- *
- * Look ahead through the traversal graph to see what might happen to the
- * given register. If we can find any reachable block that references 'reg'
- * before setting it, the register is live. Scanning stops when the register
- * is set, we loop back to the starting block, or the function returns.
- */
- static bool
- is_live(bp, reg)
- BLOCK *bp;
- int reg;
- {
- INST *ip;
- BLOCK *cp;
-
- /*
- * Clear all the mark bits
- */
- for (cp = fhead; cp != NULL ;cp = cp->next)
- cp->flags &= ~B_MARK;
-
- bp->flags |= B_MARK;
-
- if (scan_ref(bp->bfall, reg))
- return TRUE;
-
- if (scan_ref(bp->bcond, reg))
- return TRUE;
-
- for (ip = bp->first; ip != NULL ;ip = ip->next) {
- if (ip->opcode == DC && (ip->flags & LENL)) {
- BLOCK *db;
-
- if ((ip->src.astr != NULL) &&
- (db = getsym(ip->src.astr)) != NULL)
- if (scan_ref(db, reg))
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /*
- * bflow() - live/dead analysis for a given block
- *
- * Work backward from the end of the block, checking the status of registers.
- * To start with, figure out the state of each register as of the end of the
- * block. Then work backward, checking registers only as necessary.
- */
- static void
- bflow(bp)
- BLOCK *bp;
- {
- INST *ip;
- int live = 0;
- int reg;
-
- /*
- * Figure out what's alive at the end of this block.
- */
- for (reg = FIRSTREG; reg <= LASTREG ;reg++) {
- if (is_live(bp, RM(reg)))
- live |= RM(reg);
- }
- /*
- * Now work through the instructions in the block.
- */
- for (ip = bp->last; ip != NULL ;ip = ip->prev) {
- ip->live = live;
-
- for (reg = FIRSTREG; reg <= LASTREG ;reg++) {
- if (ip->rref & RM(reg))
- live |= RM(reg);
- else if (ip->rset & RM(reg))
- live &= ~RM(reg);
- }
- }
- }
-
- void
- rhealth(bp)
- BLOCK *bp;
- {
- register BLOCK *cp;
-
- bprep(bp);
-
- for (cp = bp; cp != NULL ;cp = cp->next)
- bflow(cp);
- }
-