github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/5c/reg.c (about)

     1  // Inferno utils/5c/reg.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5c/reg.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  
    32  #include "gc.h"
    33  
    34  void	addsplits(void);
    35  
    36  Reg*
    37  rega(void)
    38  {
    39  	Reg *r;
    40  
    41  	r = freer;
    42  	if(r == R) {
    43  		r = alloc(sizeof(*r));
    44  	} else
    45  		freer = r->link;
    46  
    47  	*r = zreg;
    48  	return r;
    49  }
    50  
    51  int
    52  rcmp(const void *a1, const void *a2)
    53  {
    54  	Rgn *p1, *p2;
    55  	int c1, c2;
    56  
    57  	p1 = (Rgn*)a1;
    58  	p2 = (Rgn*)a2;
    59  	c1 = p2->cost;
    60  	c2 = p1->cost;
    61  	if(c1 -= c2)
    62  		return c1;
    63  	return p2->varno - p1->varno;
    64  }
    65  
    66  void
    67  regopt(Prog *p)
    68  {
    69  	Reg *r, *r1, *r2;
    70  	Prog *p1;
    71  	int i, z;
    72  	int32 initpc, val, npc;
    73  	uint32 vreg;
    74  	Bits bit;
    75  	struct
    76  	{
    77  		int32	m;
    78  		int32	c;
    79  		Reg*	p;
    80  	} log5[6], *lp;
    81  
    82  	firstr = R;
    83  	lastr = R;
    84  	nvar = 0;
    85  	regbits = 0;
    86  	for(z=0; z<BITS; z++) {
    87  		externs.b[z] = 0;
    88  		params.b[z] = 0;
    89  		consts.b[z] = 0;
    90  		addrs.b[z] = 0;
    91  	}
    92  
    93  	/*
    94  	 * pass 1
    95  	 * build aux data structure
    96  	 * allocate pcs
    97  	 * find use and set of variables
    98  	 */
    99  	val = 5L * 5L * 5L * 5L * 5L;
   100  	lp = log5;
   101  	for(i=0; i<5; i++) {
   102  		lp->m = val;
   103  		lp->c = 0;
   104  		lp->p = R;
   105  		val /= 5L;
   106  		lp++;
   107  	}
   108  	val = 0;
   109  	for(; p != P; p = p->link) {
   110  		switch(p->as) {
   111  		case ADATA:
   112  		case AGLOBL:
   113  		case ANAME:
   114  		case ASIGNAME:
   115  		case AFUNCDATA:
   116  			continue;
   117  		}
   118  		r = rega();
   119  		if(firstr == R) {
   120  			firstr = r;
   121  			lastr = r;
   122  		} else {
   123  			lastr->link = r;
   124  			r->p1 = lastr;
   125  			lastr->s1 = r;
   126  			lastr = r;
   127  		}
   128  		r->prog = p;
   129  		r->pc = val;
   130  		val++;
   131  
   132  		lp = log5;
   133  		for(i=0; i<5; i++) {
   134  			lp->c--;
   135  			if(lp->c <= 0) {
   136  				lp->c = lp->m;
   137  				if(lp->p != R)
   138  					lp->p->log5 = r;
   139  				lp->p = r;
   140  				(lp+1)->c = 0;
   141  				break;
   142  			}
   143  			lp++;
   144  		}
   145  
   146  		r1 = r->p1;
   147  		if(r1 != R)
   148  		switch(r1->prog->as) {
   149  		case ARET:
   150  		case AB:
   151  		case ARFE:
   152  			r->p1 = R;
   153  			r1->s1 = R;
   154  		}
   155  
   156  		/*
   157  		 * left side always read
   158  		 */
   159  		bit = mkvar(&p->from, p->as==AMOVW);
   160  		for(z=0; z<BITS; z++)
   161  			r->use1.b[z] |= bit.b[z];
   162  
   163  		/*
   164  		 * right side depends on opcode
   165  		 */
   166  		bit = mkvar(&p->to, 0);
   167  		if(bany(&bit))
   168  		switch(p->as) {
   169  		default:
   170  			diag(Z, "reg: unknown asop: %A", p->as);
   171  			break;
   172  
   173  		/*
   174  		 * right side write
   175  		 */
   176  		case ANOP:
   177  		case AMOVB:
   178  		case AMOVBS:
   179  		case AMOVBU:
   180  		case AMOVH:
   181  		case AMOVHS:
   182  		case AMOVHU:
   183  		case AMOVW:
   184  		case AMOVF:
   185  		case AMOVD:
   186  			for(z=0; z<BITS; z++)
   187  				r->set.b[z] |= bit.b[z];
   188  			break;
   189  
   190  		/*
   191  		 * right side read
   192  		 */
   193  		case APLD:
   194  			for(z=0; z<BITS; z++)
   195  				r->use2.b[z] |= bit.b[z];
   196  			break;
   197  
   198  		/*
   199  		 * funny
   200  		 */
   201  		case ABL:
   202  			for(z=0; z<BITS; z++)
   203  				addrs.b[z] |= bit.b[z];
   204  			break;
   205  		}
   206  
   207  		if(p->as == AMOVM) {
   208  			if(p->from.type == D_CONST)
   209  				z = p->from.offset;
   210  			else
   211  				z = p->to.offset;
   212  			for(i=0; z; i++) {
   213  				if(z&1)
   214  					regbits |= RtoB(i);
   215  				z >>= 1;
   216  			}
   217  		}
   218  	}
   219  	if(firstr == R)
   220  		return;
   221  	initpc = pc - val;
   222  	npc = val;
   223  
   224  	/*
   225  	 * pass 2
   226  	 * turn branch references to pointers
   227  	 * build back pointers
   228  	 */
   229  	for(r = firstr; r != R; r = r->link) {
   230  		p = r->prog;
   231  		if(p->to.type == D_BRANCH) {
   232  			val = p->to.offset - initpc;
   233  			r1 = firstr;
   234  			while(r1 != R) {
   235  				r2 = r1->log5;
   236  				if(r2 != R && val >= r2->pc) {
   237  					r1 = r2;
   238  					continue;
   239  				}
   240  				if(r1->pc == val)
   241  					break;
   242  				r1 = r1->link;
   243  			}
   244  			if(r1 == R) {
   245  				nearln = p->lineno;
   246  				diag(Z, "ref not found\n%P", p);
   247  				continue;
   248  			}
   249  			if(r1 == r) {
   250  				nearln = p->lineno;
   251  				diag(Z, "ref to self\n%P", p);
   252  				continue;
   253  			}
   254  			r->s2 = r1;
   255  			r->p2link = r1->p2;
   256  			r1->p2 = r;
   257  		}
   258  	}
   259  	if(debug['R']) {
   260  		p = firstr->prog;
   261  		print("\n%L %D\n", p->lineno, &p->from);
   262  	}
   263  
   264  	/*
   265  	 * pass 2.5
   266  	 * find looping structure
   267  	 */
   268  	for(r = firstr; r != R; r = r->link)
   269  		r->active = 0;
   270  	change = 0;
   271  	loopit(firstr, npc);
   272  
   273  	/*
   274  	 * pass 3
   275  	 * iterate propagating usage
   276  	 * 	back until flow graph is complete
   277  	 */
   278  loop1:
   279  	change = 0;
   280  	for(r = firstr; r != R; r = r->link)
   281  		r->active = 0;
   282  	for(r = firstr; r != R; r = r->link)
   283  		if(r->prog->as == ARET)
   284  			prop(r, zbits, zbits);
   285  loop11:
   286  	/* pick up unreachable code */
   287  	i = 0;
   288  	for(r = firstr; r != R; r = r1) {
   289  		r1 = r->link;
   290  		if(r1 && r1->active && !r->active) {
   291  			prop(r, zbits, zbits);
   292  			i = 1;
   293  		}
   294  	}
   295  	if(i)
   296  		goto loop11;
   297  	if(change)
   298  		goto loop1;
   299  
   300  
   301  	/*
   302  	 * pass 4
   303  	 * iterate propagating register/variable synchrony
   304  	 * 	forward until graph is complete
   305  	 */
   306  loop2:
   307  	change = 0;
   308  	for(r = firstr; r != R; r = r->link)
   309  		r->active = 0;
   310  	synch(firstr, zbits);
   311  	if(change)
   312  		goto loop2;
   313  
   314  	addsplits();
   315  
   316  	if(debug['R'] && debug['v']) {
   317  		print("\nprop structure:\n");
   318  		for(r = firstr; r != R; r = r->link) {
   319  			print("%d:%P", r->loop, r->prog);
   320  			for(z=0; z<BITS; z++)
   321  				bit.b[z] = r->set.b[z] |
   322  					r->refahead.b[z] | r->calahead.b[z] |
   323  					r->refbehind.b[z] | r->calbehind.b[z] |
   324  					r->use1.b[z] | r->use2.b[z];
   325  			if(bany(&bit)) {
   326  				print("\t");
   327  				if(bany(&r->use1))
   328  					print(" u1=%B", r->use1);
   329  				if(bany(&r->use2))
   330  					print(" u2=%B", r->use2);
   331  				if(bany(&r->set))
   332  					print(" st=%B", r->set);
   333  				if(bany(&r->refahead))
   334  					print(" ra=%B", r->refahead);
   335  				if(bany(&r->calahead))
   336  					print(" ca=%B", r->calahead);
   337  				if(bany(&r->refbehind))
   338  					print(" rb=%B", r->refbehind);
   339  				if(bany(&r->calbehind))
   340  					print(" cb=%B", r->calbehind);
   341  			}
   342  			print("\n");
   343  		}
   344  	}
   345  
   346  	/*
   347  	 * pass 5
   348  	 * isolate regions
   349  	 * calculate costs (paint1)
   350  	 */
   351  	r = firstr;
   352  	if(r) {
   353  		for(z=0; z<BITS; z++)
   354  			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
   355  			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
   356  		if(bany(&bit)) {
   357  			nearln = r->prog->lineno;
   358  			warn(Z, "used and not set: %B", bit);
   359  			if(debug['R'] && !debug['w'])
   360  				print("used and not set: %B\n", bit);
   361  		}
   362  	}
   363  
   364  	for(r = firstr; r != R; r = r->link)
   365  		r->act = zbits;
   366  	rgp = region;
   367  	nregion = 0;
   368  	for(r = firstr; r != R; r = r->link) {
   369  		for(z=0; z<BITS; z++)
   370  			bit.b[z] = r->set.b[z] &
   371  			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
   372  		if(bany(&bit)) {
   373  			nearln = r->prog->lineno;
   374  			warn(Z, "set and not used: %B", bit);
   375  			if(debug['R'])
   376  				print("set and not used: %B\n", bit);
   377  			excise(r);
   378  		}
   379  		for(z=0; z<BITS; z++)
   380  			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
   381  		while(bany(&bit)) {
   382  			i = bnum(bit);
   383  			rgp->enter = r;
   384  			rgp->varno = i;
   385  			change = 0;
   386  			if(debug['R'] && debug['v'])
   387  				print("\n");
   388  			paint1(r, i);
   389  			bit.b[i/32] &= ~(1L<<(i%32));
   390  			if(change <= 0) {
   391  				if(debug['R'])
   392  					print("%L $%d: %B\n",
   393  						r->prog->lineno, change, blsh(i));
   394  				continue;
   395  			}
   396  			rgp->cost = change;
   397  			nregion++;
   398  			if(nregion >= NRGN) {
   399  				warn(Z, "too many regions");
   400  				goto brk;
   401  			}
   402  			rgp++;
   403  		}
   404  	}
   405  brk:
   406  	qsort(region, nregion, sizeof(region[0]), rcmp);
   407  
   408  	/*
   409  	 * pass 6
   410  	 * determine used registers (paint2)
   411  	 * replace code (paint3)
   412  	 */
   413  	rgp = region;
   414  	for(i=0; i<nregion; i++) {
   415  		bit = blsh(rgp->varno);
   416  		vreg = paint2(rgp->enter, rgp->varno);
   417  		vreg = allreg(vreg, rgp);
   418  		if(debug['R']) {
   419  			if(rgp->regno >= NREG)
   420  				print("%L $%d F%d: %B\n",
   421  					rgp->enter->prog->lineno,
   422  					rgp->cost,
   423  					rgp->regno-NREG,
   424  					bit);
   425  			else
   426  				print("%L $%d R%d: %B\n",
   427  					rgp->enter->prog->lineno,
   428  					rgp->cost,
   429  					rgp->regno,
   430  					bit);
   431  		}
   432  		if(rgp->regno != 0)
   433  			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
   434  		rgp++;
   435  	}
   436  	/*
   437  	 * pass 7
   438  	 * peep-hole on basic block
   439  	 */
   440  	if(!debug['R'] || debug['P'])
   441  		peep();
   442  
   443  	/*
   444  	 * pass 8
   445  	 * recalculate pc
   446  	 */
   447  	val = initpc;
   448  	for(r = firstr; r != R; r = r1) {
   449  		r->pc = val;
   450  		p = r->prog;
   451  		p1 = P;
   452  		r1 = r->link;
   453  		if(r1 != R)
   454  			p1 = r1->prog;
   455  		for(; p != p1; p = p->link) {
   456  			switch(p->as) {
   457  			default:
   458  				val++;
   459  				break;
   460  
   461  			case ANOP:
   462  			case ADATA:
   463  			case AGLOBL:
   464  			case ANAME:
   465  			case ASIGNAME:
   466  			case AFUNCDATA:
   467  				break;
   468  			}
   469  		}
   470  	}
   471  	pc = val;
   472  
   473  	/*
   474  	 * fix up branches
   475  	 */
   476  	if(debug['R'])
   477  		if(bany(&addrs))
   478  			print("addrs: %B\n", addrs);
   479  
   480  	r1 = 0; /* set */
   481  	for(r = firstr; r != R; r = r->link) {
   482  		p = r->prog;
   483  		if(p->to.type == D_BRANCH)
   484  			p->to.offset = r->s2->pc;
   485  		r1 = r;
   486  	}
   487  
   488  	/*
   489  	 * last pass
   490  	 * eliminate nops
   491  	 * free aux structures
   492  	 */
   493  	for(p = firstr->prog; p != P; p = p->link){
   494  		while(p->link && p->link->as == ANOP)
   495  			p->link = p->link->link;
   496  	}
   497  	if(r1 != R) {
   498  		r1->link = freer;
   499  		freer = firstr;
   500  	}
   501  }
   502  
   503  void
   504  addsplits(void)
   505  {
   506  	Reg *r, *r1;
   507  	int z, i;
   508  	Bits bit;
   509  
   510  	for(r = firstr; r != R; r = r->link) {
   511  		if(r->loop > 1)
   512  			continue;
   513  		if(r->prog->as == ABL)
   514  			continue;
   515  		for(r1 = r->p2; r1 != R; r1 = r1->p2link) {
   516  			if(r1->loop <= 1)
   517  				continue;
   518  			for(z=0; z<BITS; z++)
   519  				bit.b[z] = r1->calbehind.b[z] &
   520  					(r->refahead.b[z] | r->use1.b[z] | r->use2.b[z]) &
   521  					~(r->calahead.b[z] & addrs.b[z]);
   522  			while(bany(&bit)) {
   523  				i = bnum(bit);
   524  				bit.b[i/32] &= ~(1L << (i%32));
   525  			}
   526  		}
   527  	}
   528  }
   529  
   530  /*
   531   * add mov b,rn
   532   * just after r
   533   */
   534  void
   535  addmove(Reg *r, int bn, int rn, int f)
   536  {
   537  	Prog *p, *p1;
   538  	Adr *a;
   539  	Var *v;
   540  
   541  	p1 = alloc(sizeof(*p1));
   542  	*p1 = zprog;
   543  	p = r->prog;
   544  
   545  	p1->link = p->link;
   546  	p->link = p1;
   547  	p1->lineno = p->lineno;
   548  
   549  	v = var + bn;
   550  
   551  	a = &p1->to;
   552  	a->sym = v->sym;
   553  	a->name = v->name;
   554  	a->offset = v->offset;
   555  	a->etype = v->etype;
   556  	a->type = D_OREG;
   557  	if(a->etype == TARRAY || a->sym == S)
   558  		a->type = D_CONST;
   559  
   560  	p1->as = AMOVW;
   561  	if(v->etype == TCHAR || v->etype == TUCHAR)
   562  		p1->as = AMOVBS;
   563  	if(v->etype == TSHORT || v->etype == TUSHORT)
   564  		p1->as = AMOVHS;
   565  	if(v->etype == TFLOAT)
   566  		p1->as = AMOVF;
   567  	if(v->etype == TDOUBLE)
   568  		p1->as = AMOVD;
   569  
   570  	p1->from.type = D_REG;
   571  	p1->from.reg = rn;
   572  	if(rn >= NREG) {
   573  		p1->from.type = D_FREG;
   574  		p1->from.reg = rn-NREG;
   575  	}
   576  	if(!f) {
   577  		p1->from = *a;
   578  		*a = zprog.from;
   579  		a->type = D_REG;
   580  		a->reg = rn;
   581  		if(rn >= NREG) {
   582  			a->type = D_FREG;
   583  			a->reg = rn-NREG;
   584  		}
   585  		if(v->etype == TUCHAR)
   586  			p1->as = AMOVBU;
   587  		if(v->etype == TUSHORT)
   588  			p1->as = AMOVHU;
   589  	}
   590  	if(debug['R'])
   591  		print("%P\t.a%P\n", p, p1);
   592  }
   593  
   594  Bits
   595  mkvar(Adr *a, int docon)
   596  {
   597  	Var *v;
   598  	int i, t, n, et, z;
   599  	int32 o;
   600  	Bits bit;
   601  	Sym *s;
   602  
   603  	t = a->type;
   604  	if(t == D_REG && a->reg != NREG)
   605  		regbits |= RtoB(a->reg);
   606  	if(t == D_FREG && a->reg != NREG)
   607  		regbits |= FtoB(a->reg);
   608  	s = a->sym;
   609  	o = a->offset;
   610  	et = a->etype;
   611  	if(s == S) {
   612  		if(t != D_CONST || !docon || a->reg != NREG)
   613  			goto none;
   614  		et = TLONG;
   615  	}
   616  	if(t == D_CONST) {
   617  		if(s == S && sval(o))
   618  			goto none;
   619  	}
   620  
   621  	n = a->name;
   622  	v = var;
   623  	for(i=0; i<nvar; i++) {
   624  		if(s == v->sym)
   625  		if(n == v->name)
   626  		if(o == v->offset)
   627  			goto out;
   628  		v++;
   629  	}
   630  	if(s)
   631  		if(s->name[0] == '.')
   632  			goto none;
   633  	if(nvar >= NVAR) {
   634  		if(debug['w'] > 1 && s)
   635  			warn(Z, "variable not optimized: %s", s->name);
   636  		goto none;
   637  	}
   638  	i = nvar;
   639  	nvar++;
   640  	v = &var[i];
   641  	v->sym = s;
   642  	v->offset = o;
   643  	v->etype = et;
   644  	v->name = n;
   645  	if(debug['R'])
   646  		print("bit=%2d et=%2d %D\n", i, et, a);
   647  out:
   648  	bit = blsh(i);
   649  	if(n == D_EXTERN || n == D_STATIC)
   650  		for(z=0; z<BITS; z++)
   651  			externs.b[z] |= bit.b[z];
   652  	if(n == D_PARAM)
   653  		for(z=0; z<BITS; z++)
   654  			params.b[z] |= bit.b[z];
   655  	if(v->etype != et || !typechlpfd[et])	/* funny punning */
   656  		for(z=0; z<BITS; z++)
   657  			addrs.b[z] |= bit.b[z];
   658  	if(t == D_CONST) {
   659  		if(s == S) {
   660  			for(z=0; z<BITS; z++)
   661  				consts.b[z] |= bit.b[z];
   662  			return bit;
   663  		}
   664  		if(et != TARRAY)
   665  			for(z=0; z<BITS; z++)
   666  				addrs.b[z] |= bit.b[z];
   667  		for(z=0; z<BITS; z++)
   668  			params.b[z] |= bit.b[z];
   669  		return bit;
   670  	}
   671  	if(t == D_OREG)
   672  		return bit;
   673  
   674  none:
   675  	return zbits;
   676  }
   677  
   678  void
   679  prop(Reg *r, Bits ref, Bits cal)
   680  {
   681  	Reg *r1, *r2;
   682  	int z;
   683  
   684  	for(r1 = r; r1 != R; r1 = r1->p1) {
   685  		for(z=0; z<BITS; z++) {
   686  			ref.b[z] |= r1->refahead.b[z];
   687  			if(ref.b[z] != r1->refahead.b[z]) {
   688  				r1->refahead.b[z] = ref.b[z];
   689  				change++;
   690  			}
   691  			cal.b[z] |= r1->calahead.b[z];
   692  			if(cal.b[z] != r1->calahead.b[z]) {
   693  				r1->calahead.b[z] = cal.b[z];
   694  				change++;
   695  			}
   696  		}
   697  		switch(r1->prog->as) {
   698  		case ABL:
   699  			for(z=0; z<BITS; z++) {
   700  				cal.b[z] |= ref.b[z] | externs.b[z];
   701  				ref.b[z] = 0;
   702  			}
   703  			break;
   704  
   705  		case ATEXT:
   706  			for(z=0; z<BITS; z++) {
   707  				cal.b[z] = 0;
   708  				ref.b[z] = 0;
   709  			}
   710  			break;
   711  
   712  		case ARET:
   713  			for(z=0; z<BITS; z++) {
   714  				cal.b[z] = externs.b[z];
   715  				ref.b[z] = 0;
   716  			}
   717  		}
   718  		for(z=0; z<BITS; z++) {
   719  			ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
   720  				r1->use1.b[z] | r1->use2.b[z];
   721  			cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
   722  			r1->refbehind.b[z] = ref.b[z];
   723  			r1->calbehind.b[z] = cal.b[z];
   724  		}
   725  		if(r1->active)
   726  			break;
   727  		r1->active = 1;
   728  	}
   729  	for(; r != r1; r = r->p1)
   730  		for(r2 = r->p2; r2 != R; r2 = r2->p2link)
   731  			prop(r2, r->refbehind, r->calbehind);
   732  }
   733  
   734  /*
   735   * find looping structure
   736   *
   737   * 1) find reverse postordering
   738   * 2) find approximate dominators,
   739   *	the actual dominators if the flow graph is reducible
   740   *	otherwise, dominators plus some other non-dominators.
   741   *	See Matthew S. Hecht and Jeffrey D. Ullman,
   742   *	"Analysis of a Simple Algorithm for Global Data Flow Problems",
   743   *	Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
   744   *	Oct. 1-3, 1973, pp.  207-217.
   745   * 3) find all nodes with a predecessor dominated by the current node.
   746   *	such a node is a loop head.
   747   *	recursively, all preds with a greater rpo number are in the loop
   748   */
   749  int32
   750  postorder(Reg *r, Reg **rpo2r, int32 n)
   751  {
   752  	Reg *r1;
   753  
   754  	r->rpo = 1;
   755  	r1 = r->s1;
   756  	if(r1 && !r1->rpo)
   757  		n = postorder(r1, rpo2r, n);
   758  	r1 = r->s2;
   759  	if(r1 && !r1->rpo)
   760  		n = postorder(r1, rpo2r, n);
   761  	rpo2r[n] = r;
   762  	n++;
   763  	return n;
   764  }
   765  
   766  int32
   767  rpolca(int32 *idom, int32 rpo1, int32 rpo2)
   768  {
   769  	int32 t;
   770  
   771  	if(rpo1 == -1)
   772  		return rpo2;
   773  	while(rpo1 != rpo2){
   774  		if(rpo1 > rpo2){
   775  			t = rpo2;
   776  			rpo2 = rpo1;
   777  			rpo1 = t;
   778  		}
   779  		while(rpo1 < rpo2){
   780  			t = idom[rpo2];
   781  			if(t >= rpo2)
   782  				fatal(Z, "bad idom");
   783  			rpo2 = t;
   784  		}
   785  	}
   786  	return rpo1;
   787  }
   788  
   789  int
   790  doms(int32 *idom, int32 r, int32 s)
   791  {
   792  	while(s > r)
   793  		s = idom[s];
   794  	return s == r;
   795  }
   796  
   797  int
   798  loophead(int32 *idom, Reg *r)
   799  {
   800  	int32 src;
   801  
   802  	src = r->rpo;
   803  	if(r->p1 != R && doms(idom, src, r->p1->rpo))
   804  		return 1;
   805  	for(r = r->p2; r != R; r = r->p2link)
   806  		if(doms(idom, src, r->rpo))
   807  			return 1;
   808  	return 0;
   809  }
   810  
   811  void
   812  loopmark(Reg **rpo2r, int32 head, Reg *r)
   813  {
   814  	if(r->rpo < head || r->active == head)
   815  		return;
   816  	r->active = head;
   817  	r->loop += LOOP;
   818  	if(r->p1 != R)
   819  		loopmark(rpo2r, head, r->p1);
   820  	for(r = r->p2; r != R; r = r->p2link)
   821  		loopmark(rpo2r, head, r);
   822  }
   823  
   824  void
   825  loopit(Reg *r, int32 nr)
   826  {
   827  	Reg *r1;
   828  	int32 i, d, me;
   829  
   830  	if(nr > maxnr) {
   831  		rpo2r = alloc(nr * sizeof(Reg*));
   832  		idom = alloc(nr * sizeof(int32));
   833  		maxnr = nr;
   834  	}
   835  	d = postorder(r, rpo2r, 0);
   836  	if(d > nr)
   837  		fatal(Z, "too many reg nodes");
   838  	nr = d;
   839  	for(i = 0; i < nr / 2; i++){
   840  		r1 = rpo2r[i];
   841  		rpo2r[i] = rpo2r[nr - 1 - i];
   842  		rpo2r[nr - 1 - i] = r1;
   843  	}
   844  	for(i = 0; i < nr; i++)
   845  		rpo2r[i]->rpo = i;
   846  
   847  	idom[0] = 0;
   848  	for(i = 0; i < nr; i++){
   849  		r1 = rpo2r[i];
   850  		me = r1->rpo;
   851  		d = -1;
   852  		if(r1->p1 != R && r1->p1->rpo < me)
   853  			d = r1->p1->rpo;
   854  		for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
   855  			if(r1->rpo < me)
   856  				d = rpolca(idom, d, r1->rpo);
   857  		idom[i] = d;
   858  	}
   859  
   860  	for(i = 0; i < nr; i++){
   861  		r1 = rpo2r[i];
   862  		r1->loop++;
   863  		if(r1->p2 != R && loophead(idom, r1))
   864  			loopmark(rpo2r, i, r1);
   865  	}
   866  }
   867  
   868  void
   869  synch(Reg *r, Bits dif)
   870  {
   871  	Reg *r1;
   872  	int z;
   873  
   874  	for(r1 = r; r1 != R; r1 = r1->s1) {
   875  		for(z=0; z<BITS; z++) {
   876  			dif.b[z] = (dif.b[z] &
   877  				~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
   878  					r1->set.b[z] | r1->regdiff.b[z];
   879  			if(dif.b[z] != r1->regdiff.b[z]) {
   880  				r1->regdiff.b[z] = dif.b[z];
   881  				change++;
   882  			}
   883  		}
   884  		if(r1->active)
   885  			break;
   886  		r1->active = 1;
   887  		for(z=0; z<BITS; z++)
   888  			dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
   889  		if(r1->s2 != R)
   890  			synch(r1->s2, dif);
   891  	}
   892  }
   893  
   894  uint32
   895  allreg(uint32 b, Rgn *r)
   896  {
   897  	Var *v;
   898  	int i;
   899  
   900  	v = var + r->varno;
   901  	r->regno = 0;
   902  	switch(v->etype) {
   903  
   904  	default:
   905  		diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
   906  		break;
   907  
   908  	case TCHAR:
   909  	case TUCHAR:
   910  	case TSHORT:
   911  	case TUSHORT:
   912  	case TINT:
   913  	case TUINT:
   914  	case TLONG:
   915  	case TULONG:
   916  	case TIND:
   917  	case TARRAY:
   918  		i = BtoR(~b);
   919  		if(i && r->cost >= 0) {
   920  			r->regno = i;
   921  			return RtoB(i);
   922  		}
   923  		break;
   924  
   925  	case TVLONG:
   926  	case TDOUBLE:
   927  	case TFLOAT:
   928  		i = BtoF(~b);
   929  		if(i && r->cost >= 0) {
   930  			r->regno = i+NREG;
   931  			return FtoB(i);
   932  		}
   933  		break;
   934  	}
   935  	return 0;
   936  }
   937  
   938  void
   939  paint1(Reg *r, int bn)
   940  {
   941  	Reg *r1;
   942  	Prog *p;
   943  	int z;
   944  	uint32 bb;
   945  
   946  	z = bn/32;
   947  	bb = 1L<<(bn%32);
   948  	if(r->act.b[z] & bb)
   949  		return;
   950  	for(;;) {
   951  		if(!(r->refbehind.b[z] & bb))
   952  			break;
   953  		r1 = r->p1;
   954  		if(r1 == R)
   955  			break;
   956  		if(!(r1->refahead.b[z] & bb))
   957  			break;
   958  		if(r1->act.b[z] & bb)
   959  			break;
   960  		r = r1;
   961  	}
   962  
   963  	if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) {
   964  		change -= CLOAD * r->loop;
   965  		if(debug['R'] && debug['v'])
   966  			print("%d%P\td %B $%d\n", r->loop,
   967  				r->prog, blsh(bn), change);
   968  	}
   969  	for(;;) {
   970  		r->act.b[z] |= bb;
   971  		p = r->prog;
   972  
   973  		if(r->use1.b[z] & bb) {
   974  			change += CREF * r->loop;
   975  			if(debug['R'] && debug['v'])
   976  				print("%d%P\tu1 %B $%d\n", r->loop,
   977  					p, blsh(bn), change);
   978  		}
   979  
   980  		if((r->use2.b[z]|r->set.b[z]) & bb) {
   981  			change += CREF * r->loop;
   982  			if(debug['R'] && debug['v'])
   983  				print("%d%P\tu2 %B $%d\n", r->loop,
   984  					p, blsh(bn), change);
   985  		}
   986  
   987  		if(STORE(r) & r->regdiff.b[z] & bb) {
   988  			change -= CLOAD * r->loop;
   989  			if(debug['R'] && debug['v'])
   990  				print("%d%P\tst %B $%d\n", r->loop,
   991  					p, blsh(bn), change);
   992  		}
   993  
   994  		if(r->refbehind.b[z] & bb)
   995  			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
   996  				if(r1->refahead.b[z] & bb)
   997  					paint1(r1, bn);
   998  
   999  		if(!(r->refahead.b[z] & bb))
  1000  			break;
  1001  		r1 = r->s2;
  1002  		if(r1 != R)
  1003  			if(r1->refbehind.b[z] & bb)
  1004  				paint1(r1, bn);
  1005  		r = r->s1;
  1006  		if(r == R)
  1007  			break;
  1008  		if(r->act.b[z] & bb)
  1009  			break;
  1010  		if(!(r->refbehind.b[z] & bb))
  1011  			break;
  1012  	}
  1013  }
  1014  
  1015  uint32
  1016  paint2(Reg *r, int bn)
  1017  {
  1018  	Reg *r1;
  1019  	int z;
  1020  	uint32 bb, vreg;
  1021  
  1022  	z = bn/32;
  1023  	bb = 1L << (bn%32);
  1024  	vreg = regbits;
  1025  	if(!(r->act.b[z] & bb))
  1026  		return vreg;
  1027  	for(;;) {
  1028  		if(!(r->refbehind.b[z] & bb))
  1029  			break;
  1030  		r1 = r->p1;
  1031  		if(r1 == R)
  1032  			break;
  1033  		if(!(r1->refahead.b[z] & bb))
  1034  			break;
  1035  		if(!(r1->act.b[z] & bb))
  1036  			break;
  1037  		r = r1;
  1038  	}
  1039  	for(;;) {
  1040  		r->act.b[z] &= ~bb;
  1041  
  1042  		vreg |= r->regu;
  1043  
  1044  		if(r->refbehind.b[z] & bb)
  1045  			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
  1046  				if(r1->refahead.b[z] & bb)
  1047  					vreg |= paint2(r1, bn);
  1048  
  1049  		if(!(r->refahead.b[z] & bb))
  1050  			break;
  1051  		r1 = r->s2;
  1052  		if(r1 != R)
  1053  			if(r1->refbehind.b[z] & bb)
  1054  				vreg |= paint2(r1, bn);
  1055  		r = r->s1;
  1056  		if(r == R)
  1057  			break;
  1058  		if(!(r->act.b[z] & bb))
  1059  			break;
  1060  		if(!(r->refbehind.b[z] & bb))
  1061  			break;
  1062  	}
  1063  	return vreg;
  1064  }
  1065  
  1066  void
  1067  paint3(Reg *r, int bn, int32 rb, int rn)
  1068  {
  1069  	Reg *r1;
  1070  	Prog *p;
  1071  	int z;
  1072  	uint32 bb;
  1073  
  1074  	z = bn/32;
  1075  	bb = 1L << (bn%32);
  1076  	if(r->act.b[z] & bb)
  1077  		return;
  1078  	for(;;) {
  1079  		if(!(r->refbehind.b[z] & bb))
  1080  			break;
  1081  		r1 = r->p1;
  1082  		if(r1 == R)
  1083  			break;
  1084  		if(!(r1->refahead.b[z] & bb))
  1085  			break;
  1086  		if(r1->act.b[z] & bb)
  1087  			break;
  1088  		r = r1;
  1089  	}
  1090  
  1091  	if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
  1092  		addmove(r, bn, rn, 0);
  1093  	for(;;) {
  1094  		r->act.b[z] |= bb;
  1095  		p = r->prog;
  1096  
  1097  		if(r->use1.b[z] & bb) {
  1098  			if(debug['R'])
  1099  				print("%P", p);
  1100  			addreg(&p->from, rn);
  1101  			if(debug['R'])
  1102  				print("\t.c%P\n", p);
  1103  		}
  1104  		if((r->use2.b[z]|r->set.b[z]) & bb) {
  1105  			if(debug['R'])
  1106  				print("%P", p);
  1107  			addreg(&p->to, rn);
  1108  			if(debug['R'])
  1109  				print("\t.c%P\n", p);
  1110  		}
  1111  
  1112  		if(STORE(r) & r->regdiff.b[z] & bb)
  1113  			addmove(r, bn, rn, 1);
  1114  		r->regu |= rb;
  1115  
  1116  		if(r->refbehind.b[z] & bb)
  1117  			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
  1118  				if(r1->refahead.b[z] & bb)
  1119  					paint3(r1, bn, rb, rn);
  1120  
  1121  		if(!(r->refahead.b[z] & bb))
  1122  			break;
  1123  		r1 = r->s2;
  1124  		if(r1 != R)
  1125  			if(r1->refbehind.b[z] & bb)
  1126  				paint3(r1, bn, rb, rn);
  1127  		r = r->s1;
  1128  		if(r == R)
  1129  			break;
  1130  		if(r->act.b[z] & bb)
  1131  			break;
  1132  		if(!(r->refbehind.b[z] & bb))
  1133  			break;
  1134  	}
  1135  }
  1136  
  1137  void
  1138  addreg(Adr *a, int rn)
  1139  {
  1140  
  1141  	a->sym = 0;
  1142  	a->name = D_NONE;
  1143  	a->type = D_REG;
  1144  	a->reg = rn;
  1145  	if(rn >= NREG) {
  1146  		a->type = D_FREG;
  1147  		a->reg = rn-NREG;
  1148  	}
  1149  }
  1150  
  1151  /*
  1152   *	bit	reg
  1153   *	0	R0
  1154   *	1	R1
  1155   *	...	...
  1156   *	10	R10
  1157   *	12  R12
  1158   */
  1159  int32
  1160  RtoB(int r)
  1161  {
  1162  
  1163  	if(r < 2 || (r >= REGTMP-2 && r != 12))	// excluded R9 and R10 for m and g, but not R12
  1164  		return 0;
  1165  	return 1L << r;
  1166  }
  1167  
  1168  int
  1169  BtoR(int32 b)
  1170  {
  1171  	b &= 0x11fcL;	// excluded R9 and R10 for m and g, but not R12
  1172  	if(b == 0)
  1173  		return 0;
  1174  	return bitno(b);
  1175  }
  1176  
  1177  /*
  1178   *	bit	reg
  1179   *	18	F2
  1180   *	19	F3
  1181   *	...	...
  1182   *	31	F15
  1183   */
  1184  int32
  1185  FtoB(int f)
  1186  {
  1187  
  1188  	if(f < 2 || f > NFREG-1)
  1189  		return 0;
  1190  	return 1L << (f + 16);
  1191  }
  1192  
  1193  int
  1194  BtoF(int32 b)
  1195  {
  1196  
  1197  	b &= 0xfffc0000L;
  1198  	if(b == 0)
  1199  		return 0;
  1200  	return bitno(b) - 16;
  1201  }