optloop.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 780 行

C
780
字号
#ifndef lintstatic	char	*sccsid = "@(#)optloop.c	4.1	(ULTRIX)	7/17/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1984 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * optloop.c * * Loop optimizations, f77 compiler pass 1, 4.2 BSD. * * University of Utah CS Dept. modification history: * * $Log:	optloop.c,v $ * Revision 1.4  84/10/25  01:27:29  donn * Fixed a subtle bug in removesafe().  When the moved code is an assignment * into a temporary, we use the lhs to substitute for the expression inside * the loop.  Previously the data structure for the temporary was not copied, * so later on when the lhs was freed, the substitute was too, turning it * into garbage. *  * Revision 1.3  84/08/05  17:04:03  donn * Changed worthcost() so that it skips variable length strings -- we can't * make temporaries for these... *  * Revision 1.2  84/07/19  11:50:39  donn * Installed changes to force non-intrinsic subroutines and functions to define * their arguments (make them ineligible for optimization), function setsuses. * Fix from A.F. *  */#include "defs.h"#include "optim.h"#define SCFREE   0#define SCSAFE   1typedef  struct varblock    {      struct varblock *next;      field vstg;      int memno;	/* holds memalloc for TTEMP */      short sets;      short uses;      field setfirst;    } VARBLOCK;typedef VARBLOCK *Varp;#define TABLESIZE 59LOCAL Varp table[TABLESIZE];LOCAL Varp mkbucket(vstg,memno)field vstg;int memno;{  Varp q;  q = ALLOC(varblock);  q->vstg = vstg;  q->memno = memno;  return q;}LOCAL Varp lookup(p)tagptr p;{int vstg, memno;int key;Varp q, r;switch (p->tag)	{	case TTEMP:		vstg = 0;		memno = (int) p->tempblock.memalloc;		break;	case TADDR:		vstg = p->addrblock.vstg;		memno = p->addrblock.memno;		break;	default:		badtag ("lookup",p->tag);	}key = memno % TABLESIZE;q = table[key];if (q)	{	for (; q; r = q, q = q->next)		if ((q->vstg == vstg) && (q->memno == memno))			return q;	return r->next = mkbucket(vstg,memno);	}else	return table[key] = mkbucket(vstg,memno);}LOCAL freetable(){  int i;  Varp p, q;  for (i = 0; i < TABLESIZE; i++)    if (table[i])      {	p = table[i];	table[i] = NULL;	while (p)	  {	    q = p->next;	    free((char *) p);	    p = q;	  }      }}Slotp newcode;Slotp dohead, doend;LOCAL Slotp first, last;LOCAL commonset;LOCAL int comocount;	/* count of number of code motions done */optloops(){int	match;Slotp	nextslot;Slotp	sl1,sl2;Slotp	lastlabslot;int	lab;if (! optimflag) return;if (debugflag[6]) return;lastlabslot = NULL;comocount = 0;for (sl1 = firstslot; sl1; sl1 = nextslot)	{	nextslot = sl1->next;	switch (sl1->type)	    {	    case SKLABEL:		lastlabslot = sl1;		break;	    case SKGOTO:		if (lastlabslot && sl1->label == lastlabslot->label)			{			lab = newlabel ();			first = optinsert (SKLABEL,0,lab,0,lastlabslot->next);			last = sl1;			last->label = lab;			optloop ();			}		break;	    case SKDOHEAD:		match = 0;		for (sl2 = sl1; sl2; sl2 = sl2->next)			{			if (sl2->type == SKDOHEAD) match++;			else if (sl2->type == SKENDDO) match--;			if (match == 0) break;			}		if (sl2)			last = sl2;		else			fatal ("unmatched do in code buffer");		if (sl2->type != SKENDDO)			fatal ("internal error in optloops");		/*  last now points to the SKENDDO slot; the SKNULL slot		 *  is reached through last->nullslot		 */		last = (Slotp) last->nullslot;		first = sl1;		optloop ();		break;	    default:		break;	    }	}if (debugflag[0])	fprintf (diagfile,"%d code motion%s performed\n",comocount,		(comocount==1 ? "" : "s") );return;}optloop(){newcode = NULL;modify();return;}LOCAL modify(){  Slotp sp;  int s;  scanvars();  for (sp = first; sp != last->next; sp = sp->next)    switch (sp->type)      {      case SKEQ:	s = anex(sp->expr);	if (s == SCSAFE)	  removesafe (&sp->expr);	break;      case SKARIF:      case SKASGOTO:      case SKCALL:      case SKCMGOTO:      case SKIFN:      case SKSTOP:      case SKRETURN:      case SKPAUSE:      case SKIOIFN:	s = anex(sp->expr);	if (s == SCSAFE)	  removesafe(&sp->expr);	break;      default:	break;      }  freetable();  return;}LOCAL scanvars(){  Slotp sp;  Varp varinfo;  int i;  Varp p;  commonset = NO;  for (sp = first; sp != last->next; sp = sp->next)    {      switch (sp->type)	{	case SKARIF:	case SKASGOTO:	case SKCALL:	case SKCMGOTO:	case SKIFN:	case SKSTOP:	case SKRETURN:	case SKPAUSE:	case SKIOIFN:	case SKEQ:	  setsuses(sp->expr);	  break;	default:	  break;	}    }  if (commonset)    for (i = 0; i < TABLESIZE; i++)      for (p = table[i]; p; p = p->next)	if (p->vstg == STGCOMMON)	  {	    p->sets++;	    p->setfirst = NO;	  }}LOCAL setsuses(p)expptr p;{  Addrp lhs;  Varp varinfo;  chainp args;  if (!p) return;  switch (p->tag)    {    case TEXPR:      switch (p->exprblock.opcode)	{	default:	  setsuses(p->exprblock.leftp);	  setsuses(p->exprblock.rightp);	  setsuses(p->exprblock.vleng);	  break;	case OPASSIGN:	  switch (p->exprblock.leftp->tag)	    {	    case TTEMP:	      lhs = (Addrp) p->exprblock.leftp;	      goto taddr;	    case TADDR:	      lhs = (Addrp) p->exprblock.leftp;	      setsuses(lhs->memoffset);	      setsuses(lhs->vleng);	    taddr:	      setsuses(p->exprblock.rightp);	      setsuses(p->exprblock.vleng);	      varinfo = lookup(lhs);	      varinfo->sets++;              if (varinfo->uses == 0)	        varinfo->setfirst = YES;	      break;	    default:	      fatal("O6:  l-value expected");	    }	  break;	case OPSTAREQ:	case OPPLUSEQ:	  switch (p->exprblock.leftp->tag)	    {	    case TADDR:	      lhs = (Addrp) p->exprblock.leftp;	      break;	    case TTEMP:	      lhs = (Addrp) p->exprblock.leftp;	      break;	    default:	      fatal("O7:  l-value expected");	    }	  setsuses(p->exprblock.leftp);	  setsuses(p->exprblock.rightp);	  setsuses(p->exprblock.vleng);	  varinfo = lookup(lhs);	  varinfo->sets++;	  break;	case OPCALL:	  if (p->exprblock.leftp->tag != TADDR)	    fatal("O8:  subprogram expected");	  setsuses(p->exprblock.rightp);	  setsuses(p->exprblock.vleng);	  if (p->exprblock.leftp->addrblock.vstg == STGINTR) break;	  commonset = YES;	  if (p->exprblock.rightp == NULL) break;	  args = p->exprblock.rightp->listblock.listp;	  for (; args; args = args->nextp)	    if (args->datap->tag == TADDR)	      {		lhs = (Addrp) args->datap;		switch (lhs->vstg)		  {		  case STGARG:		  case STGAUTO:		  case STGBSS:		  case STGINIT:		  case STGCOMMON:		  case STGEQUIV:		  case STGREG:		  case STGPREG:		    varinfo = lookup(lhs);		    varinfo->sets++;		  }	      }	    else if (args->datap->tag == TTEMP)	      {		lhs = (Addrp) args->datap;		varinfo = lookup (lhs);		varinfo->sets++;	      }	  break;        }      return;    case TTEMP:      varinfo = lookup((Addrp) p);      varinfo->uses++;      return;    case TADDR:      setsuses(p->addrblock.memoffset);      setsuses(p->addrblock.vleng);      varinfo = lookup((Addrp) p);      varinfo->uses++;      return;    case TLIST:      for (args = p->listblock.listp; args; args = args->nextp)	setsuses(args->datap);    case TCONST:    case TERROR:      return;    default:      fatal("O9:  bad tag value");    }}LOCAL int anex(p)expptr p;{  int s1, s2, s3;  expptr q;  Varp varinfo;  chainp ch;  int setfirst;  expptr expr;  if (p == ENULL)    return SCSAFE;  switch (p->tag)    {    case TCONST:      return SCSAFE;    case TLIST:      for (ch = p->listblock.listp; ch; ch = ch->nextp)	{	  s1 = anex (ch->datap);	  if (s1 == SCSAFE)	    removesafe (&ch->datap);	}      return SCFREE;    case TEXPR:      s1 = anex(p->exprblock.leftp);      s2 = anex(p->exprblock.rightp);      s3 = anex(p->exprblock.vleng);      switch (p->exprblock.opcode)	{	case OPASSIGN:	  expr = p->exprblock.leftp;	  varinfo = lookup(expr);	  setfirst = varinfo->setfirst && (varinfo->sets == 1);	  if (expr->tag == TTEMP && setfirst &&		s2 == SCSAFE && s3 == SCSAFE)	    {	      movefrtemp (expr);	      return SCSAFE;	    }	  else	    {	      if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);	      if (s3 == SCSAFE) removesafe (&p->exprblock.vleng);	      return SCFREE;	    }	case OPNEG:	case OPNOT:	case OPABS:	case OPADDR:	case OPBITNOT:	  if ((s2 == SCSAFE) && (s3 == SCSAFE))	    return s1;	  else	    return SCFREE;	case OPCONV:	  if ((s2 != SCSAFE) || (s3 != SCSAFE))	    return SCFREE;	  if (ISINT(p->exprblock.vtype))	    return s1;	  if (ISINT(p->exprblock.leftp->headblock.vtype))	    return s1;	  return SCFREE;	case OPSTAR:	  if (ISINT(p->exprblock.vtype))	    goto safeop;	  if (safefactor(p->exprblock.leftp) ||	      safefactor(p->exprblock.rightp))	    goto safeop;	  goto floatop;	case OPPLUS:	case OPMINUS:	  if (ISINT(p->exprblock.vtype))	    goto safeop;	floatop:	  if (!(ISREAL(p->exprblock.vtype) || ISCOMPLEX(p->exprblock.vtype)))	    return SCFREE;	  switch (s1)	    {	    case SCSAFE:	      removesafe(&p->exprblock.leftp);	      if (s2 == SCSAFE)		removesafe(&p->exprblock.leftp);	      return SCFREE;	    case SCFREE:	      if (s2 == SCSAFE)		removesafe(&p->exprblock.rightp);	      return SCFREE;	    }	case OPOR:	case OPAND:	case OPEQV:	case OPNEQV:	case OPLT:	case OPEQ:	case OPGT:	case OPLE:	case OPNE:	case OPGE:	case OPLSHIFT:	case OPMIN:	case OPMAX:	case OPBITOR:	case OPBITAND:	case OPBITXOR:	case OPRSHIFT:	safeop:	  if ((p->exprblock.vleng != ENULL) && ( ! ISCONST(p->exprblock.vleng)))	    return SCFREE;	  switch (s1)	    {	    case SCSAFE:		if (s2 == SCFREE) removesafe (&p->exprblock.leftp);		return s2;	    case SCFREE:		if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);		return SCFREE;	    }	default:	  if (s1 == SCSAFE) removesafe(&p->exprblock.leftp);	  if (s2 == SCSAFE) removesafe(&p->exprblock.rightp);	  if (s3 == SCSAFE) removesafe(&p->exprblock.vleng);	  return SCFREE;	}    case TTEMP:      varinfo = lookup(p);      if (varinfo->sets == 0)	return SCSAFE;      else	return SCFREE;    case TADDR:      s1 = anex(p->addrblock.memoffset);      s2 = anex(p->addrblock.vleng);      varinfo = lookup(p);      if (varinfo->sets == 0)	switch (s1)	  {	  case SCSAFE:		if (s2 == SCFREE) removesafe(&p->addrblock.memoffset);		return s2;	  case SCFREE:		if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);		return SCFREE;	  }      if (s1 == SCSAFE) removesafe(&p->addrblock.memoffset);      if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);      return SCFREE;    	    default:      return SCFREE;    }}LOCAL safefactor(p)expptr p;{  if ( ! ISCONST(p))    return NO;  if (ISINT(p->constblock.vtype))    if (abs(p->constblock.const.ci) <= 1)      return YES;  if (ISREAL(p->constblock.vtype))    if (abs(p->constblock.const.cd[0]) <= 1.0)      return YES;  return NO;}LOCAL int worthcost(p)expptr p;{  int cost;  chainp q;  expptr memoffset,vleng;  if (p == ENULL)    return NO;  switch (p->tag)    {    case TCONST:      return NO;    case TTEMP:      return NO;    case TADDR:      if ((vleng = p->addrblock.vleng) && ! ISCONST(vleng))	return NO;	/* Can't make variable length temporaries */      if ((memoffset = p->addrblock.memoffset) && ! ISCONST(memoffset))	return YES;      else	return NO;    case TEXPR:      return YES;    case TLIST:      cost = 0;      for (q = p->listblock.listp; q; q = q->nextp)	{	if (worthcost ((expptr) q->datap))	  return YES;	cost++;	}      return (cost>2 ? YES : NO);    default:      return NO;    }}LOCAL removesafe(refexpr)expptr *refexpr;{  expptr ep;  Tempp ap;  Slotp newslot;  extern Addrp gettemp();  ep = *refexpr;  if (! worthcost(ep))    return;  if (ep->tag == TEXPR && ep->exprblock.opcode == OPASSIGN)    {      if (ep->exprblock.leftp->tag != TTEMP)	fatal ("non-TEMP in assignment to be moved in optloop");      newslot = optinsert (SKEQ, ep, 0, 0, first);      *refexpr = (expptr) cpexpr (ep->exprblock.leftp);    }  else    {      ap = (Tempp) gettemp(ep);      newslot = optinsert (SKEQ, mkexpr(OPASSIGN,cpexpr(ap),ep), 0, 0, first);      *refexpr = (expptr) ap;      optinsert (SKFRTEMP,ap->memalloc,0,0,last->next);    }  comocount++;  if (!newcode)    newcode = newslot;  return;}LOCAL Addrp gettemp(p)expptr p;{  return mktemp(p->headblock.vtype, p->headblock.vleng);}LOCAL movefrtemp (expr)Tempp	expr;{  Slotp	s;  if (expr->tag != TTEMP)    badtag ("movefrtemp",expr->tag);  for (s = first; s; s = s->next)    if (s->type == SKFRTEMP && s->expr == (expptr) expr->memalloc)      {	removeslot (s);	insertslot (s,last->next);	return;      }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?