github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/8g/peep.c (about)

     1  // Derived from Inferno utils/6c/peep.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.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  #include <u.h>
    32  #include <libc.h>
    33  #include "gg.h"
    34  #include "opt.h"
    35  
    36  #define	REGEXT	0
    37  
    38  static void	conprop(Reg *r);
    39  static void elimshortmov(Reg *r);
    40  
    41  // do we need the carry bit
    42  static int
    43  needc(Prog *p)
    44  {
    45  	while(p != P) {
    46  		switch(p->as) {
    47  		case AADCL:
    48  		case ASBBL:
    49  		case ARCRB:
    50  		case ARCRW:
    51  		case ARCRL:
    52  			return 1;
    53  		case AADDB:
    54  		case AADDW:
    55  		case AADDL:
    56  		case ASUBB:
    57  		case ASUBW:
    58  		case ASUBL:
    59  		case AJMP:
    60  		case ARET:
    61  		case ACALL:
    62  			return 0;
    63  		default:
    64  			if(p->to.type == D_BRANCH)
    65  				return 0;
    66  		}
    67  		p = p->link;
    68  	}
    69  	return 0;
    70  }
    71  
    72  static Reg*
    73  rnops(Reg *r)
    74  {
    75  	Prog *p;
    76  	Reg *r1;
    77  
    78  	if(r != R)
    79  	for(;;) {
    80  		p = r->prog;
    81  		if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
    82  			break;
    83  		r1 = uniqs(r);
    84  		if(r1 == R)
    85  			break;
    86  		r = r1;
    87  	}
    88  	return r;
    89  }
    90  
    91  void
    92  peep(void)
    93  {
    94  	Reg *r, *r1, *r2;
    95  	Prog *p, *p1;
    96  	int t;
    97  
    98  	/*
    99  	 * complete R structure
   100  	 */
   101  	t = 0;
   102  	for(r=firstr; r!=R; r=r1) {
   103  		r1 = r->link;
   104  		if(r1 == R)
   105  			break;
   106  		p = r->prog->link;
   107  		while(p != r1->prog)
   108  		switch(p->as) {
   109  		default:
   110  			r2 = rega();
   111  			r->link = r2;
   112  			r2->link = r1;
   113  
   114  			r2->prog = p;
   115  			p->reg = r2;
   116  
   117  			r2->p1 = r;
   118  			r->s1 = r2;
   119  			r2->s1 = r1;
   120  			r1->p1 = r2;
   121  
   122  			r = r2;
   123  			t++;
   124  
   125  		case ADATA:
   126  		case AGLOBL:
   127  		case ANAME:
   128  		case ASIGNAME:
   129  		case ALOCALS:
   130  		case ATYPE:
   131  			p = p->link;
   132  		}
   133  	}
   134  
   135  	// byte, word arithmetic elimination.
   136  	elimshortmov(r);
   137  
   138  	// constant propagation
   139  	// find MOV $con,R followed by
   140  	// another MOV $con,R without
   141  	// setting R in the interim
   142  	for(r=firstr; r!=R; r=r->link) {
   143  		p = r->prog;
   144  		switch(p->as) {
   145  		case ALEAL:
   146  			if(regtyp(&p->to))
   147  			if(p->from.sym != S)
   148  				conprop(r);
   149  			break;
   150  
   151  		case AMOVB:
   152  		case AMOVW:
   153  		case AMOVL:
   154  		case AMOVSS:
   155  		case AMOVSD:
   156  			if(regtyp(&p->to))
   157  			if(p->from.type == D_CONST)
   158  				conprop(r);
   159  			break;
   160  		}
   161  	}
   162  
   163  loop1:
   164  	if(debug['P'] && debug['v'])
   165  		dumpit("loop1", firstr);
   166  
   167  	t = 0;
   168  	for(r=firstr; r!=R; r=r->link) {
   169  		p = r->prog;
   170  		switch(p->as) {
   171  		case AMOVL:
   172  		case AMOVSS:
   173  		case AMOVSD:
   174  			if(regtyp(&p->to))
   175  			if(regtyp(&p->from)) {
   176  				if(copyprop(r)) {
   177  					excise(r);
   178  					t++;
   179  				} else
   180  				if(subprop(r) && copyprop(r)) {
   181  					excise(r);
   182  					t++;
   183  				}
   184  			}
   185  			break;
   186  
   187  		case AMOVBLZX:
   188  		case AMOVWLZX:
   189  		case AMOVBLSX:
   190  		case AMOVWLSX:
   191  			if(regtyp(&p->to)) {
   192  				r1 = rnops(uniqs(r));
   193  				if(r1 != R) {
   194  					p1 = r1->prog;
   195  					if(p->as == p1->as && p->to.type == p1->from.type){
   196  						p1->as = AMOVL;
   197  						t++;
   198  					}
   199  				}
   200  			}
   201  			break;
   202  
   203  		case AADDL:
   204  		case AADDW:
   205  			if(p->from.type != D_CONST || needc(p->link))
   206  				break;
   207  			if(p->from.offset == -1){
   208  				if(p->as == AADDL)
   209  					p->as = ADECL;
   210  				else
   211  					p->as = ADECW;
   212  				p->from = zprog.from;
   213  				break;
   214  			}
   215  			if(p->from.offset == 1){
   216  				if(p->as == AADDL)
   217  					p->as = AINCL;
   218  				else
   219  					p->as = AINCW;
   220  				p->from = zprog.from;
   221  				break;
   222  			}
   223  			break;
   224  
   225  		case ASUBL:
   226  		case ASUBW:
   227  			if(p->from.type != D_CONST || needc(p->link))
   228  				break;
   229  			if(p->from.offset == -1) {
   230  				if(p->as == ASUBL)
   231  					p->as = AINCL;
   232  				else
   233  					p->as = AINCW;
   234  				p->from = zprog.from;
   235  				break;
   236  			}
   237  			if(p->from.offset == 1){
   238  				if(p->as == ASUBL)
   239  					p->as = ADECL;
   240  				else
   241  					p->as = ADECW;
   242  				p->from = zprog.from;
   243  				break;
   244  			}
   245  			break;
   246  		}
   247  	}
   248  	if(t)
   249  		goto loop1;
   250  
   251  	// MOVSD removal.
   252  	// We never use packed registers, so a MOVSD between registers
   253  	// can be replaced by MOVAPD, which moves the pair of float64s
   254  	// instead of just the lower one.  We only use the lower one, but
   255  	// the processor can do better if we do moves using both.
   256  	for(r=firstr; r!=R; r=r->link) {
   257  		p = r->prog;
   258  		if(p->as == AMOVSD)
   259  		if(regtyp(&p->from))
   260  		if(regtyp(&p->to))
   261  			p->as = AMOVAPD;
   262  	}
   263  }
   264  
   265  void
   266  excise(Reg *r)
   267  {
   268  	Prog *p;
   269  
   270  	p = r->prog;
   271  	if(debug['P'] && debug['v'])
   272  		print("%P ===delete===\n", p);
   273  
   274  	p->as = ANOP;
   275  	p->from = zprog.from;
   276  	p->to = zprog.to;
   277  
   278  	ostats.ndelmov++;
   279  }
   280  
   281  Reg*
   282  uniqp(Reg *r)
   283  {
   284  	Reg *r1;
   285  
   286  	r1 = r->p1;
   287  	if(r1 == R) {
   288  		r1 = r->p2;
   289  		if(r1 == R || r1->p2link != R)
   290  			return R;
   291  	} else
   292  		if(r->p2 != R)
   293  			return R;
   294  	return r1;
   295  }
   296  
   297  Reg*
   298  uniqs(Reg *r)
   299  {
   300  	Reg *r1;
   301  
   302  	r1 = r->s1;
   303  	if(r1 == R) {
   304  		r1 = r->s2;
   305  		if(r1 == R)
   306  			return R;
   307  	} else
   308  		if(r->s2 != R)
   309  			return R;
   310  	return r1;
   311  }
   312  
   313  int
   314  regtyp(Adr *a)
   315  {
   316  	int t;
   317  
   318  	t = a->type;
   319  	if(t >= D_AX && t <= D_DI)
   320  		return 1;
   321  	if(t >= D_X0 && t <= D_X7)
   322  		return 1;
   323  	return 0;
   324  }
   325  
   326  // movb elimination.
   327  // movb is simulated by the linker
   328  // when a register other than ax, bx, cx, dx
   329  // is used, so rewrite to other instructions
   330  // when possible.  a movb into a register
   331  // can smash the entire 64-bit register without
   332  // causing any trouble.
   333  static void
   334  elimshortmov(Reg *r)
   335  {
   336  	Prog *p;
   337  
   338  	for(r=firstr; r!=R; r=r->link) {
   339  		p = r->prog;
   340  		if(regtyp(&p->to)) {
   341  			switch(p->as) {
   342  			case AINCB:
   343  			case AINCW:
   344  				p->as = AINCL;
   345  				break;
   346  			case ADECB:
   347  			case ADECW:
   348  				p->as = ADECL;
   349  				break;
   350  			case ANEGB:
   351  			case ANEGW:
   352  				p->as = ANEGL;
   353  				break;
   354  			case ANOTB:
   355  			case ANOTW:
   356  				p->as = ANOTL;
   357  				break;
   358  			}
   359  			if(regtyp(&p->from) || p->from.type == D_CONST) {
   360  				// move or artihmetic into partial register.
   361  				// from another register or constant can be movl.
   362  				// we don't switch to 32-bit arithmetic if it can
   363  				// change how the carry bit is set (and the carry bit is needed).
   364  				switch(p->as) {
   365  				case AMOVB:
   366  				case AMOVW:
   367  					p->as = AMOVL;
   368  					break;
   369  				case AADDB:
   370  				case AADDW:
   371  					if(!needc(p->link))
   372  						p->as = AADDL;
   373  					break;
   374  				case ASUBB:
   375  				case ASUBW:
   376  					if(!needc(p->link))
   377  						p->as = ASUBL;
   378  					break;
   379  				case AMULB:
   380  				case AMULW:
   381  					p->as = AMULL;
   382  					break;
   383  				case AIMULB:
   384  				case AIMULW:
   385  					p->as = AIMULL;
   386  					break;
   387  				case AANDB:
   388  				case AANDW:
   389  					p->as = AANDL;
   390  					break;
   391  				case AORB:
   392  				case AORW:
   393  					p->as = AORL;
   394  					break;
   395  				case AXORB:
   396  				case AXORW:
   397  					p->as = AXORL;
   398  					break;
   399  				case ASHLB:
   400  				case ASHLW:
   401  					p->as = ASHLL;
   402  					break;
   403  				}
   404  			} else {
   405  				// explicit zero extension
   406  				switch(p->as) {
   407  				case AMOVB:
   408  					p->as = AMOVBLZX;
   409  					break;
   410  				case AMOVW:
   411  					p->as = AMOVWLZX;
   412  					break;
   413  				}
   414  			}
   415  		}
   416  	}
   417  }
   418  
   419  /*
   420   * the idea is to substitute
   421   * one register for another
   422   * from one MOV to another
   423   *	MOV	a, R0
   424   *	ADD	b, R0	/ no use of R1
   425   *	MOV	R0, R1
   426   * would be converted to
   427   *	MOV	a, R1
   428   *	ADD	b, R1
   429   *	MOV	R1, R0
   430   * hopefully, then the former or latter MOV
   431   * will be eliminated by copy propagation.
   432   */
   433  int
   434  subprop(Reg *r0)
   435  {
   436  	Prog *p;
   437  	Adr *v1, *v2;
   438  	Reg *r;
   439  	int t;
   440  
   441  	p = r0->prog;
   442  	v1 = &p->from;
   443  	if(!regtyp(v1))
   444  		return 0;
   445  	v2 = &p->to;
   446  	if(!regtyp(v2))
   447  		return 0;
   448  	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
   449  		if(uniqs(r) == R)
   450  			break;
   451  		p = r->prog;
   452  		switch(p->as) {
   453  		case ACALL:
   454  			return 0;
   455  
   456  		case AIMULL:
   457  		case AIMULW:
   458  			if(p->to.type != D_NONE)
   459  				break;
   460  
   461  		case ARCLB:
   462  		case ARCLL:
   463  		case ARCLW:
   464  		case ARCRB:
   465  		case ARCRL:
   466  		case ARCRW:
   467  		case AROLB:
   468  		case AROLL:
   469  		case AROLW:
   470  		case ARORB:
   471  		case ARORL:
   472  		case ARORW:
   473  		case ASALB:
   474  		case ASALL:
   475  		case ASALW:
   476  		case ASARB:
   477  		case ASARL:
   478  		case ASARW:
   479  		case ASHLB:
   480  		case ASHLL:
   481  		case ASHLW:
   482  		case ASHRB:
   483  		case ASHRL:
   484  		case ASHRW:
   485  			if(p->from.type == D_CONST)
   486  				break;
   487  
   488  		case ADIVB:
   489  		case ADIVL:
   490  		case ADIVW:
   491  		case AIDIVB:
   492  		case AIDIVL:
   493  		case AIDIVW:
   494  		case AIMULB:
   495  		case AMULB:
   496  		case AMULL:
   497  		case AMULW:
   498  
   499  		case AREP:
   500  		case AREPN:
   501  
   502  		case ACWD:
   503  		case ACDQ:
   504  
   505  		case ASTOSB:
   506  		case ASTOSL:
   507  		case AMOVSB:
   508  		case AMOVSL:
   509  
   510  		case AFMOVF:
   511  		case AFMOVD:
   512  		case AFMOVFP:
   513  		case AFMOVDP:
   514  			return 0;
   515  
   516  		case AMOVL:
   517  		case AMOVSS:
   518  		case AMOVSD:
   519  			if(p->to.type == v1->type)
   520  				goto gotit;
   521  			break;
   522  		}
   523  		if(copyau(&p->from, v2) ||
   524  		   copyau(&p->to, v2))
   525  			break;
   526  		if(copysub(&p->from, v1, v2, 0) ||
   527  		   copysub(&p->to, v1, v2, 0))
   528  			break;
   529  	}
   530  	return 0;
   531  
   532  gotit:
   533  	copysub(&p->to, v1, v2, 1);
   534  	if(debug['P']) {
   535  		print("gotit: %D->%D\n%P", v1, v2, r->prog);
   536  		if(p->from.type == v2->type)
   537  			print(" excise");
   538  		print("\n");
   539  	}
   540  	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
   541  		p = r->prog;
   542  		copysub(&p->from, v1, v2, 1);
   543  		copysub(&p->to, v1, v2, 1);
   544  		if(debug['P'])
   545  			print("%P\n", r->prog);
   546  	}
   547  	t = v1->type;
   548  	v1->type = v2->type;
   549  	v2->type = t;
   550  	if(debug['P'])
   551  		print("%P last\n", r->prog);
   552  	return 1;
   553  }
   554  
   555  /*
   556   * The idea is to remove redundant copies.
   557   *	v1->v2	F=0
   558   *	(use v2	s/v2/v1/)*
   559   *	set v1	F=1
   560   *	use v2	return fail
   561   *	-----------------
   562   *	v1->v2	F=0
   563   *	(use v2	s/v2/v1/)*
   564   *	set v1	F=1
   565   *	set v2	return success
   566   */
   567  int
   568  copyprop(Reg *r0)
   569  {
   570  	Prog *p;
   571  	Adr *v1, *v2;
   572  	Reg *r;
   573  
   574  	p = r0->prog;
   575  	v1 = &p->from;
   576  	v2 = &p->to;
   577  	if(copyas(v1, v2))
   578  		return 1;
   579  	for(r=firstr; r!=R; r=r->link)
   580  		r->active = 0;
   581  	return copy1(v1, v2, r0->s1, 0);
   582  }
   583  
   584  int
   585  copy1(Adr *v1, Adr *v2, Reg *r, int f)
   586  {
   587  	int t;
   588  	Prog *p;
   589  
   590  	if(r->active) {
   591  		if(debug['P'])
   592  			print("act set; return 1\n");
   593  		return 1;
   594  	}
   595  	r->active = 1;
   596  	if(debug['P'])
   597  		print("copy %D->%D f=%d\n", v1, v2, f);
   598  	for(; r != R; r = r->s1) {
   599  		p = r->prog;
   600  		if(debug['P'])
   601  			print("%P", p);
   602  		if(!f && uniqp(r) == R) {
   603  			f = 1;
   604  			if(debug['P'])
   605  				print("; merge; f=%d", f);
   606  		}
   607  		t = copyu(p, v2, A);
   608  		switch(t) {
   609  		case 2:	/* rar, cant split */
   610  			if(debug['P'])
   611  				print("; %D rar; return 0\n", v2);
   612  			return 0;
   613  
   614  		case 3:	/* set */
   615  			if(debug['P'])
   616  				print("; %D set; return 1\n", v2);
   617  			return 1;
   618  
   619  		case 1:	/* used, substitute */
   620  		case 4:	/* use and set */
   621  			if(f) {
   622  				if(!debug['P'])
   623  					return 0;
   624  				if(t == 4)
   625  					print("; %D used+set and f=%d; return 0\n", v2, f);
   626  				else
   627  					print("; %D used and f=%d; return 0\n", v2, f);
   628  				return 0;
   629  			}
   630  			if(copyu(p, v2, v1)) {
   631  				if(debug['P'])
   632  					print("; sub fail; return 0\n");
   633  				return 0;
   634  			}
   635  			if(debug['P'])
   636  				print("; sub %D/%D", v2, v1);
   637  			if(t == 4) {
   638  				if(debug['P'])
   639  					print("; %D used+set; return 1\n", v2);
   640  				return 1;
   641  			}
   642  			break;
   643  		}
   644  		if(!f) {
   645  			t = copyu(p, v1, A);
   646  			if(!f && (t == 2 || t == 3 || t == 4)) {
   647  				f = 1;
   648  				if(debug['P'])
   649  					print("; %D set and !f; f=%d", v1, f);
   650  			}
   651  		}
   652  		if(debug['P'])
   653  			print("\n");
   654  		if(r->s2)
   655  			if(!copy1(v1, v2, r->s2, f))
   656  				return 0;
   657  	}
   658  	return 1;
   659  }
   660  
   661  /*
   662   * return
   663   * 1 if v only used (and substitute),
   664   * 2 if read-alter-rewrite
   665   * 3 if set
   666   * 4 if set and used
   667   * 0 otherwise (not touched)
   668   */
   669  int
   670  copyu(Prog *p, Adr *v, Adr *s)
   671  {
   672  
   673  	switch(p->as) {
   674  
   675  	default:
   676  		if(debug['P'])
   677  			print("unknown op %A\n", p->as);
   678  		/* SBBL; ADCL; FLD1; SAHF */
   679  		return 2;
   680  
   681  
   682  	case ANEGB:
   683  	case ANEGW:
   684  	case ANEGL:
   685  	case ANOTB:
   686  	case ANOTW:
   687  	case ANOTL:
   688  		if(copyas(&p->to, v))
   689  			return 2;
   690  		break;
   691  
   692  	case ALEAL:	/* lhs addr, rhs store */
   693  		if(copyas(&p->from, v))
   694  			return 2;
   695  
   696  
   697  	case ANOP:	/* rhs store */
   698  	case AMOVL:
   699  	case AMOVBLSX:
   700  	case AMOVBLZX:
   701  	case AMOVWLSX:
   702  	case AMOVWLZX:
   703  	
   704  	case AMOVSS:
   705  	case AMOVSD:
   706  	case ACVTSD2SL:
   707  	case ACVTSD2SS:
   708  	case ACVTSL2SD:
   709  	case ACVTSL2SS:
   710  	case ACVTSS2SD:
   711  	case ACVTSS2SL:
   712  	case ACVTTSD2SL:
   713  	case ACVTTSS2SL:
   714  		if(copyas(&p->to, v)) {
   715  			if(s != A)
   716  				return copysub(&p->from, v, s, 1);
   717  			if(copyau(&p->from, v))
   718  				return 4;
   719  			return 3;
   720  		}
   721  		goto caseread;
   722  
   723  	case ARCLB:
   724  	case ARCLL:
   725  	case ARCLW:
   726  	case ARCRB:
   727  	case ARCRL:
   728  	case ARCRW:
   729  	case AROLB:
   730  	case AROLL:
   731  	case AROLW:
   732  	case ARORB:
   733  	case ARORL:
   734  	case ARORW:
   735  	case ASALB:
   736  	case ASALL:
   737  	case ASALW:
   738  	case ASARB:
   739  	case ASARL:
   740  	case ASARW:
   741  	case ASHLB:
   742  	case ASHLL:
   743  	case ASHLW:
   744  	case ASHRB:
   745  	case ASHRL:
   746  	case ASHRW:
   747  		if(copyas(&p->to, v))
   748  			return 2;
   749  		if(copyas(&p->from, v))
   750  			if(p->from.type == D_CX)
   751  				return 2;
   752  		goto caseread;
   753  
   754  	case AADDB:	/* rhs rar */
   755  	case AADDL:
   756  	case AADDW:
   757  	case AANDB:
   758  	case AANDL:
   759  	case AANDW:
   760  	case ADECL:
   761  	case ADECW:
   762  	case AINCL:
   763  	case AINCW:
   764  	case ASUBB:
   765  	case ASUBL:
   766  	case ASUBW:
   767  	case AORB:
   768  	case AORL:
   769  	case AORW:
   770  	case AXORB:
   771  	case AXORL:
   772  	case AXORW:
   773  	case AMOVB:
   774  	case AMOVW:
   775  
   776  	case AADDSD:
   777  	case AADDSS:
   778  	case ACMPSD:
   779  	case ACMPSS:
   780  	case ADIVSD:
   781  	case ADIVSS:
   782  	case AMAXSD:
   783  	case AMAXSS:
   784  	case AMINSD:
   785  	case AMINSS:
   786  	case AMULSD:
   787  	case AMULSS:
   788  	case ARCPSS:
   789  	case ARSQRTSS:
   790  	case ASQRTSD:
   791  	case ASQRTSS:
   792  	case ASUBSD:
   793  	case ASUBSS:
   794  	case AXORPD:
   795  		if(copyas(&p->to, v))
   796  			return 2;
   797  		goto caseread;
   798  
   799  	case ACMPL:	/* read only */
   800  	case ACMPW:
   801  	case ACMPB:
   802  
   803  	case ACOMISD:
   804  	case ACOMISS:
   805  	case AUCOMISD:
   806  	case AUCOMISS:
   807  	caseread:
   808  		if(s != A) {
   809  			if(copysub(&p->from, v, s, 1))
   810  				return 1;
   811  			return copysub(&p->to, v, s, 1);
   812  		}
   813  		if(copyau(&p->from, v))
   814  			return 1;
   815  		if(copyau(&p->to, v))
   816  			return 1;
   817  		break;
   818  
   819  	case AJGE:	/* no reference */
   820  	case AJNE:
   821  	case AJLE:
   822  	case AJEQ:
   823  	case AJHI:
   824  	case AJLS:
   825  	case AJMI:
   826  	case AJPL:
   827  	case AJGT:
   828  	case AJLT:
   829  	case AJCC:
   830  	case AJCS:
   831  
   832  	case AADJSP:
   833  	case AWAIT:
   834  	case ACLD:
   835  		break;
   836  
   837  	case AIMULL:
   838  	case AIMULW:
   839  		if(p->to.type != D_NONE) {
   840  			if(copyas(&p->to, v))
   841  				return 2;
   842  			goto caseread;
   843  		}
   844  
   845  	case ADIVB:
   846  	case ADIVL:
   847  	case ADIVW:
   848  	case AIDIVB:
   849  	case AIDIVL:
   850  	case AIDIVW:
   851  	case AIMULB:
   852  	case AMULB:
   853  	case AMULL:
   854  	case AMULW:
   855  
   856  	case ACWD:
   857  	case ACDQ:
   858  		if(v->type == D_AX || v->type == D_DX)
   859  			return 2;
   860  		goto caseread;
   861  
   862  	case AREP:
   863  	case AREPN:
   864  		if(v->type == D_CX)
   865  			return 2;
   866  		goto caseread;
   867  
   868  	case AMOVSB:
   869  	case AMOVSL:
   870  		if(v->type == D_DI || v->type == D_SI)
   871  			return 2;
   872  		goto caseread;
   873  
   874  	case ASTOSB:
   875  	case ASTOSL:
   876  		if(v->type == D_AX || v->type == D_DI)
   877  			return 2;
   878  		goto caseread;
   879  
   880  	case AJMP:	/* funny */
   881  		if(s != A) {
   882  			if(copysub(&p->to, v, s, 1))
   883  				return 1;
   884  			return 0;
   885  		}
   886  		if(copyau(&p->to, v))
   887  			return 1;
   888  		return 0;
   889  
   890  	case ARET:	/* funny */
   891  		if(s != A)
   892  			return 1;
   893  		return 3;
   894  
   895  	case ACALL:	/* funny */
   896  		if(REGEXT && v->type <= REGEXT && v->type > exregoffset)
   897  			return 2;
   898  		if(REGARG >= 0 && v->type == (uchar)REGARG)
   899  			return 2;
   900  		if(v->type == p->from.type)
   901  			return 2;
   902  
   903  		if(s != A) {
   904  			if(copysub(&p->to, v, s, 1))
   905  				return 1;
   906  			return 0;
   907  		}
   908  		if(copyau(&p->to, v))
   909  			return 4;
   910  		return 3;
   911  
   912  	case ATEXT:	/* funny */
   913  		if(REGARG >= 0 && v->type == (uchar)REGARG)
   914  			return 3;
   915  		return 0;
   916  	}
   917  	return 0;
   918  }
   919  
   920  /*
   921   * direct reference,
   922   * could be set/use depending on
   923   * semantics
   924   */
   925  int
   926  copyas(Adr *a, Adr *v)
   927  {
   928  	if(a->type != v->type)
   929  		return 0;
   930  	if(regtyp(v))
   931  		return 1;
   932  	if(v->type == D_AUTO || v->type == D_PARAM)
   933  		if(v->offset == a->offset)
   934  			return 1;
   935  	return 0;
   936  }
   937  
   938  /*
   939   * either direct or indirect
   940   */
   941  int
   942  copyau(Adr *a, Adr *v)
   943  {
   944  
   945  	if(copyas(a, v))
   946  		return 1;
   947  	if(regtyp(v)) {
   948  		if(a->type-D_INDIR == v->type)
   949  			return 1;
   950  		if(a->index == v->type)
   951  			return 1;
   952  	}
   953  	return 0;
   954  }
   955  
   956  /*
   957   * substitute s for v in a
   958   * return failure to substitute
   959   */
   960  int
   961  copysub(Adr *a, Adr *v, Adr *s, int f)
   962  {
   963  	int t;
   964  
   965  	if(copyas(a, v)) {
   966  		t = s->type;
   967  		if(t >= D_AX && t <= D_DI || t >= D_X0 && t <= D_X7) {
   968  			if(f)
   969  				a->type = t;
   970  		}
   971  		return 0;
   972  	}
   973  	if(regtyp(v)) {
   974  		t = v->type;
   975  		if(a->type == t+D_INDIR) {
   976  			if((s->type == D_BP) && a->index != D_NONE)
   977  				return 1;	/* can't use BP-base with index */
   978  			if(f)
   979  				a->type = s->type+D_INDIR;
   980  //			return 0;
   981  		}
   982  		if(a->index == t) {
   983  			if(f)
   984  				a->index = s->type;
   985  			return 0;
   986  		}
   987  		return 0;
   988  	}
   989  	return 0;
   990  }
   991  
   992  static void
   993  conprop(Reg *r0)
   994  {
   995  	Reg *r;
   996  	Prog *p, *p0;
   997  	int t;
   998  	Adr *v0;
   999  
  1000  	p0 = r0->prog;
  1001  	v0 = &p0->to;
  1002  	r = r0;
  1003  
  1004  loop:
  1005  	r = uniqs(r);
  1006  	if(r == R || r == r0)
  1007  		return;
  1008  	if(uniqp(r) == R)
  1009  		return;
  1010  
  1011  	p = r->prog;
  1012  	t = copyu(p, v0, A);
  1013  	switch(t) {
  1014  	case 0:	// miss
  1015  	case 1:	// use
  1016  		goto loop;
  1017  
  1018  	case 2:	// rar
  1019  	case 4:	// use and set
  1020  		break;
  1021  
  1022  	case 3:	// set
  1023  		if(p->as == p0->as)
  1024  		if(p->from.type == p0->from.type)
  1025  		if(p->from.node == p0->from.node)
  1026  		if(p->from.offset == p0->from.offset)
  1027  		if(p->from.scale == p0->from.scale)
  1028  		if(p->from.u.vval == p0->from.u.vval)
  1029  		if(p->from.index == p0->from.index) {
  1030  			excise(r);
  1031  			goto loop;
  1032  		}
  1033  		break;
  1034  	}
  1035  }