github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/cmd/9g/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  static int	regzer(Addr *a);
    37  static int	subprop(Flow*);
    38  static int	copyprop(Flow*);
    39  static int	copy1(Addr*, Addr*, Flow*, int);
    40  static int	copyas(Addr*, Addr*);
    41  static int	copyau(Addr*, Addr*);
    42  static int	copysub(Addr*, Addr*, Addr*, int);
    43  static int	copysub1(Prog*, Addr*, Addr*, int);
    44  static int	copyau1(Prog *p, Addr *v);
    45  
    46  static uint32	gactive;
    47  
    48  void
    49  peep(Prog *firstp)
    50  {
    51  	Graph *g;
    52  	Flow *r, *r1;
    53  	Prog *p, *p1;
    54  	int t;
    55  
    56  	g = flowstart(firstp, sizeof(Flow));
    57  	if(g == nil)
    58  		return;
    59  	gactive = 0;
    60  
    61  loop1:
    62  	if(debug['P'] && debug['v'])
    63  		dumpit("loop1", g->start, 0);
    64  
    65  	t = 0;
    66  	for(r=g->start; r!=nil; r=r->link) {
    67  		p = r->prog;
    68  		// TODO(austin) Handle smaller moves.  arm and amd64
    69  		// distinguish between moves that moves that *must*
    70  		// sign/zero extend and moves that don't care so they
    71  		// can eliminate moves that don't care without
    72  		// breaking moves that do care.  This might let us
    73  		// simplify or remove the next peep loop, too.
    74  		if(p->as == AMOVD || p->as == AFMOVD)
    75  		if(regtyp(&p->to)) {
    76  			// Try to eliminate reg->reg moves
    77  			if(regtyp(&p->from))
    78  			if(p->from.type == p->to.type) {
    79  				if(copyprop(r)) {
    80  					excise(r);
    81  					t++;
    82  				} else
    83  				if(subprop(r) && copyprop(r)) {
    84  					excise(r);
    85  					t++;
    86  				}
    87  			}
    88  			// Convert uses to $0 to uses of R0 and
    89  			// propagate R0
    90  			if(regzer(&p->from))
    91  			if(p->to.type == D_REG) {
    92  				p->from.type = D_REG;
    93  				p->from.reg = REGZERO;
    94  				if(copyprop(r)) {
    95  					excise(r);
    96  					t++;
    97  				} else
    98  				if(subprop(r) && copyprop(r)) {
    99  					excise(r);
   100  					t++;
   101  				}
   102  			}
   103  		}
   104  	}
   105  	if(t)
   106  		goto loop1;
   107  
   108  	/*
   109  	 * look for MOVB x,R; MOVB R,R (for small MOVs not handled above)
   110  	 */
   111  	for(r=g->start; r!=nil; r=r->link) {
   112  		p = r->prog;
   113  		switch(p->as) {
   114  		default:
   115  			continue;
   116  		case AMOVH:
   117  		case AMOVHZ:
   118  		case AMOVB:
   119  		case AMOVBZ:
   120  		case AMOVW:
   121  		case AMOVWZ:
   122  			if(p->to.type != D_REG)
   123  				continue;
   124  			break;
   125  		}
   126  		r1 = r->link;
   127  		if(r1 == nil)
   128  			continue;
   129  		p1 = r1->prog;
   130  		if(p1->as != p->as)
   131  			continue;
   132  		if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
   133  			continue;
   134  		if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
   135  			continue;
   136  		excise(r1);
   137  	}
   138  
   139  	if(debug['D'] > 1)
   140  		goto ret;	/* allow following code improvement to be suppressed */
   141  
   142  	/*
   143  	 * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
   144  	 * when OP can set condition codes correctly
   145  	 */
   146  	for(r=g->start; r!=nil; r=r->link) {
   147  		p = r->prog;
   148  		switch(p->as) {
   149  		case ACMP:
   150  		case ACMPW:		/* always safe? */
   151  			if(!regzer(&p->to))
   152  				continue;
   153  			r1 = r->s1;
   154  			if(r1 == nil)
   155  				continue;
   156  			switch(r1->prog->as) {
   157  			default:
   158  				continue;
   159  			case ABCL:
   160  			case ABC:
   161  				/* the conditions can be complex and these are currently little used */
   162  				continue;
   163  			case ABEQ:
   164  			case ABGE:
   165  			case ABGT:
   166  			case ABLE:
   167  			case ABLT:
   168  			case ABNE:
   169  			case ABVC:
   170  			case ABVS:
   171  				break;
   172  			}
   173  			r1 = r;
   174  			do
   175  				r1 = uniqp(r1);
   176  			while (r1 != nil && r1->prog->as == ANOP);
   177  			if(r1 == nil)
   178  				continue;
   179  			p1 = r1->prog;
   180  			if(p1->to.type != D_REG || p1->to.reg != p->from.reg)
   181  				continue;
   182  			switch(p1->as) {
   183  			case ASUB:
   184  			case AADD:
   185  			case AXOR:
   186  			case AOR:
   187  				/* irregular instructions */
   188  				if(p1->from.type == D_CONST)
   189  					continue;
   190  				break;
   191  			}
   192  			switch(p1->as) {
   193  			default:
   194  				continue;
   195  			case AMOVW:
   196  			case AMOVD:
   197  				if(p1->from.type != D_REG)
   198  					continue;
   199  				continue;
   200  			case AANDCC:
   201  			case AANDNCC:
   202  			case AORCC:
   203  			case AORNCC:
   204  			case AXORCC:
   205  			case ASUBCC:
   206  			case ASUBECC:
   207  			case ASUBMECC:
   208  			case ASUBZECC:
   209  			case AADDCC:
   210  			case AADDCCC:
   211  			case AADDECC:
   212  			case AADDMECC:
   213  			case AADDZECC:
   214  			case ARLWMICC:
   215  			case ARLWNMCC:
   216  			/* don't deal with floating point instructions for now */
   217  /*
   218  			case AFABS:
   219  			case AFADD:
   220  			case AFADDS:
   221  			case AFCTIW:
   222  			case AFCTIWZ:
   223  			case AFDIV:
   224  			case AFDIVS:
   225  			case AFMADD:
   226  			case AFMADDS:
   227  			case AFMOVD:
   228  			case AFMSUB:
   229  			case AFMSUBS:
   230  			case AFMUL:
   231  			case AFMULS:
   232  			case AFNABS:
   233  			case AFNEG:
   234  			case AFNMADD:
   235  			case AFNMADDS:
   236  			case AFNMSUB:
   237  			case AFNMSUBS:
   238  			case AFRSP:
   239  			case AFSUB:
   240  			case AFSUBS:
   241  			case ACNTLZW:
   242  			case AMTFSB0:
   243  			case AMTFSB1:
   244  */
   245  			case AADD:
   246  			case AADDV:
   247  			case AADDC:
   248  			case AADDCV:
   249  			case AADDME:
   250  			case AADDMEV:
   251  			case AADDE:
   252  			case AADDEV:
   253  			case AADDZE:
   254  			case AADDZEV:
   255  			case AAND:
   256  			case AANDN:
   257  			case ADIVW:
   258  			case ADIVWV:
   259  			case ADIVWU:
   260  			case ADIVWUV:
   261  			case ADIVD:
   262  			case ADIVDV:
   263  			case ADIVDU:
   264  			case ADIVDUV:
   265  			case AEQV:
   266  			case AEXTSB:
   267  			case AEXTSH:
   268  			case AEXTSW:
   269  			case AMULHW:
   270  			case AMULHWU:
   271  			case AMULLW:
   272  			case AMULLWV:
   273  			case AMULHD:
   274  			case AMULHDU:
   275  			case AMULLD:
   276  			case AMULLDV:
   277  			case ANAND:
   278  			case ANEG:
   279  			case ANEGV:
   280  			case ANOR:
   281  			case AOR:
   282  			case AORN:
   283  			case AREM:
   284  			case AREMV:
   285  			case AREMU:
   286  			case AREMUV:
   287  			case AREMD:
   288  			case AREMDV:
   289  			case AREMDU:
   290  			case AREMDUV:
   291  			case ARLWMI:
   292  			case ARLWNM:
   293  			case ASLW:
   294  			case ASRAW:
   295  			case ASRW:
   296  			case ASLD:
   297  			case ASRAD:
   298  			case ASRD:
   299  			case ASUB:
   300  			case ASUBV:
   301  			case ASUBC:
   302  			case ASUBCV:
   303  			case ASUBME:
   304  			case ASUBMEV:
   305  			case ASUBE:
   306  			case ASUBEV:
   307  			case ASUBZE:
   308  			case ASUBZEV:
   309  			case AXOR:
   310  				t = variant2as(p1->as, as2variant(p1->as) | V_CC);
   311  				break;
   312  			}
   313  			if(debug['D'])
   314  				print("cmp %P; %P -> ", p1, p);
   315  			p1->as = t;
   316  			if(debug['D'])
   317  				print("%P\n", p1);
   318  			excise(r);
   319  			continue;
   320  		}
   321  	}
   322  
   323  ret:
   324  	flowend(g);
   325  }
   326  
   327  void
   328  excise(Flow *r)
   329  {
   330  	Prog *p, *l;
   331  
   332  	p = r->prog;
   333  	if(debug['P'] && debug['v'])
   334  		print("%P ===delete===\n", p);
   335  	l = p->link;
   336  	*p = zprog;
   337  	p->as = ANOP;
   338  	p->link = l;
   339  	ostats.ndelmov++;
   340  }
   341  
   342  /*
   343   * regzer returns 1 if a's value is 0 (a is R0 or $0)
   344   */
   345  static int
   346  regzer(Addr *a)
   347  {
   348  	if(a->type == D_CONST)
   349  		if(a->sym == nil && a->reg == NREG)
   350  			if(a->offset == 0)
   351  				return 1;
   352  	if(a->type == D_REG)
   353  		if(a->reg == REGZERO)
   354  			return 1;
   355  	return 0;
   356  }
   357  
   358  int
   359  regtyp(Adr *a)
   360  {
   361  	switch(a->type) {
   362  	default:
   363  		return 0;
   364  	case D_REG:
   365  		if(a->reg == REGZERO)
   366  			return 0;
   367  	case D_FREG:
   368  		return 1;
   369  	}
   370  }
   371  
   372  /*
   373   * the idea is to substitute
   374   * one register for another
   375   * from one MOV to another
   376   *	MOV	a, R1
   377   *	ADD	b, R1	/ no use of R2
   378   *	MOV	R1, R2
   379   * would be converted to
   380   *	MOV	a, R2
   381   *	ADD	b, R2
   382   *	MOV	R2, R1
   383   * hopefully, then the former or latter MOV
   384   * will be eliminated by copy propagation.
   385   *
   386   * r0 (the argument, not the register) is the MOV at the end of the
   387   * above sequences.  This returns 1 if it modified any instructions.
   388   */
   389  static int
   390  subprop(Flow *r0)
   391  {
   392  	Prog *p;
   393  	Addr *v1, *v2;
   394  	Flow *r;
   395  	int t;
   396  	ProgInfo info;
   397  
   398  	p = r0->prog;
   399  	v1 = &p->from;
   400  	if(!regtyp(v1))
   401  		return 0;
   402  	v2 = &p->to;
   403  	if(!regtyp(v2))
   404  		return 0;
   405  	for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
   406  		if(uniqs(r) == nil)
   407  			break;
   408  		p = r->prog;
   409  		if(p->as == AVARDEF || p->as == AVARKILL)
   410  			continue;
   411  		proginfo(&info, p);
   412  		if(info.flags & Call)
   413  			return 0;
   414  
   415  		if((info.flags & (RightRead|RightWrite)) == RightWrite) {
   416  			if(p->to.type == v1->type)
   417  			if(p->to.reg == v1->reg)
   418  				goto gotit;
   419  		}
   420  
   421  		if(copyau(&p->from, v2) ||
   422  		   copyau1(p, v2) ||
   423  		   copyau(&p->to, v2))
   424  			break;
   425  		if(copysub(&p->from, v1, v2, 0) ||
   426  		   copysub1(p, v1, v2, 0) ||
   427  		   copysub(&p->to, v1, v2, 0))
   428  			break;
   429  	}
   430  	return 0;
   431  
   432  gotit:
   433  	copysub(&p->to, v1, v2, 1);
   434  	if(debug['P']) {
   435  		print("gotit: %D->%D\n%P", v1, v2, r->prog);
   436  		if(p->from.type == v2->type)
   437  			print(" excise");
   438  		print("\n");
   439  	}
   440  	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
   441  		p = r->prog;
   442  		copysub(&p->from, v1, v2, 1);
   443  		copysub1(p, v1, v2, 1);
   444  		copysub(&p->to, v1, v2, 1);
   445  		if(debug['P'])
   446  			print("%P\n", r->prog);
   447  	}
   448  	t = v1->reg;
   449  	v1->reg = v2->reg;
   450  	v2->reg = t;
   451  	if(debug['P'])
   452  		print("%P last\n", r->prog);
   453  	return 1;
   454  }
   455  
   456  /*
   457   * The idea is to remove redundant copies.
   458   *	v1->v2	F=0
   459   *	(use v2	s/v2/v1/)*
   460   *	set v1	F=1
   461   *	use v2	return fail (v1->v2 move must remain)
   462   *	-----------------
   463   *	v1->v2	F=0
   464   *	(use v2	s/v2/v1/)*
   465   *	set v1	F=1
   466   *	set v2	return success (caller can remove v1->v2 move)
   467   */
   468  static int
   469  copyprop(Flow *r0)
   470  {
   471  	Prog *p;
   472  	Addr *v1, *v2;
   473  
   474  	p = r0->prog;
   475  	v1 = &p->from;
   476  	v2 = &p->to;
   477  	if(copyas(v1, v2)) {
   478  		if(debug['P'])
   479  			print("eliminating self-move\n", r0->prog);
   480  		return 1;
   481  	}
   482  	gactive++;
   483  	if(debug['P'])
   484  		print("trying to eliminate %D->%D move from:\n%P\n", v1, v2, r0->prog);
   485  	return copy1(v1, v2, r0->s1, 0);
   486  }
   487  
   488  // copy1 replaces uses of v2 with v1 starting at r and returns 1 if
   489  // all uses were rewritten.
   490  static int
   491  copy1(Addr *v1, Addr *v2, Flow *r, int f)
   492  {
   493  	int t;
   494  	Prog *p;
   495  
   496  	if(r->active == gactive) {
   497  		if(debug['P'])
   498  			print("act set; return 1\n");
   499  		return 1;
   500  	}
   501  	r->active = gactive;
   502  	if(debug['P'])
   503  		print("copy1 replace %D with %D f=%d\n", v2, v1, f);
   504  	for(; r != nil; r = r->s1) {
   505  		p = r->prog;
   506  		if(debug['P'])
   507  			print("%P", p);
   508  		if(!f && uniqp(r) == nil) {
   509  			// Multiple predecessors; conservatively
   510  			// assume v1 was set on other path
   511  			f = 1;
   512  			if(debug['P'])
   513  				print("; merge; f=%d", f);
   514  		}
   515  		t = copyu(p, v2, nil);
   516  		switch(t) {
   517  		case 2:	/* rar, can't split */
   518  			if(debug['P'])
   519  				print("; %D rar; return 0\n", v2);
   520  			return 0;
   521  
   522  		case 3:	/* set */
   523  			if(debug['P'])
   524  				print("; %D set; return 1\n", v2);
   525  			return 1;
   526  
   527  		case 1:	/* used, substitute */
   528  		case 4:	/* use and set */
   529  			if(f) {
   530  				if(!debug['P'])
   531  					return 0;
   532  				if(t == 4)
   533  					print("; %D used+set and f=%d; return 0\n", v2, f);
   534  				else
   535  					print("; %D used and f=%d; return 0\n", v2, f);
   536  				return 0;
   537  			}
   538  			if(copyu(p, v2, v1)) {
   539  				if(debug['P'])
   540  					print("; sub fail; return 0\n");
   541  				return 0;
   542  			}
   543  			if(debug['P'])
   544  				print("; sub %D->%D\n => %P", v2, v1, p);
   545  			if(t == 4) {
   546  				if(debug['P'])
   547  					print("; %D used+set; return 1\n", v2);
   548  				return 1;
   549  			}
   550  			break;
   551  		}
   552  		if(!f) {
   553  			t = copyu(p, v1, nil);
   554  			if(!f && (t == 2 || t == 3 || t == 4)) {
   555  				f = 1;
   556  				if(debug['P'])
   557  					print("; %D set and !f; f=%d", v1, f);
   558  			}
   559  		}
   560  		if(debug['P'])
   561  			print("\n");
   562  		if(r->s2)
   563  			if(!copy1(v1, v2, r->s2, f))
   564  				return 0;
   565  	}
   566  	return 1;
   567  }
   568  
   569  // If s==nil, copyu returns the set/use of v in p; otherwise, it
   570  // modifies p to replace reads of v with reads of s and returns 0 for
   571  // success or non-zero for failure.
   572  //
   573  // If s==nil, copy returns one of the following values:
   574  // 	1 if v only used
   575  //	2 if v is set and used in one address (read-alter-rewrite;
   576  // 	  can't substitute)
   577  //	3 if v is only set
   578  //	4 if v is set in one address and used in another (so addresses
   579  // 	  can be rewritten independently)
   580  //	0 otherwise (not touched)
   581  int
   582  copyu(Prog *p, Addr *v, Addr *s)
   583  {
   584  	if(p->from3.type != D_NONE)
   585  		// 9g never generates a from3
   586  		print("copyu: from3 (%D) not implemented\n", p->from3);
   587  
   588  	switch(p->as) {
   589  
   590  	default:
   591  		print("copyu: can't find %A\n", p->as);
   592  		return 2;
   593  
   594  	case ANOP:	/* read p->from, write p->to */
   595  	case AMOVH:
   596  	case AMOVHZ:
   597  	case AMOVB:
   598  	case AMOVBZ:
   599  	case AMOVW:
   600  	case AMOVWZ:
   601  	case AMOVD:
   602  
   603  	case ANEG:
   604  	case ANEGCC:
   605  	case AADDME:
   606  	case AADDMECC:
   607  	case AADDZE:
   608  	case AADDZECC:
   609  	case ASUBME:
   610  	case ASUBMECC:
   611  	case ASUBZE:
   612  	case ASUBZECC:
   613  
   614  	case AFCTIW:
   615  	case AFCTIWZ:
   616  	case AFCTID:
   617  	case AFCTIDZ:
   618  	case AFCFID:
   619  	case AFCFIDCC:
   620  	case AFMOVS:
   621  	case AFMOVD:
   622  	case AFRSP:
   623  	case AFNEG:
   624  	case AFNEGCC:
   625  		if(s != nil) {
   626  			if(copysub(&p->from, v, s, 1))
   627  				return 1;
   628  			// Update only indirect uses of v in p->to
   629  			if(!copyas(&p->to, v))
   630  				if(copysub(&p->to, v, s, 1))
   631  					return 1;
   632  			return 0;
   633  		}
   634  		if(copyas(&p->to, v)) {
   635  			// Fix up implicit from
   636  			if(p->from.type == D_NONE)
   637  				p->from = p->to;
   638  			if(copyau(&p->from, v))
   639  				return 4;
   640  			return 3;
   641  		}
   642  		if(copyau(&p->from, v))
   643  			return 1;
   644  		if(copyau(&p->to, v))
   645  			// p->to only indirectly uses v
   646  			return 1;
   647  		return 0;
   648  
   649  	case AMOVBU:	/* rar p->from, write p->to or read p->from, rar p->to */
   650  	case AMOVBZU:
   651  	case AMOVHU:
   652  	case AMOVHZU:
   653  	case AMOVWZU:
   654  	case AMOVDU:
   655  		if(p->from.type == D_OREG) {
   656  			if(copyas(&p->from, v))
   657  				// No s!=nil check; need to fail
   658  				// anyway in that case
   659  				return 2;
   660  			if(s != nil) {
   661  				if(copysub(&p->to, v, s, 1))
   662  					return 1;
   663  				return 0;
   664  			}
   665  			if(copyas(&p->to, v))
   666  				return 3;
   667  		} else if (p->to.type == D_OREG) {
   668  			if(copyas(&p->to, v))
   669  				return 2;
   670  			if(s != nil) {
   671  				if(copysub(&p->from, v, s, 1))
   672  					return 1;
   673  				return 0;
   674  			}
   675  			if(copyau(&p->from, v))
   676  				return 1;
   677  		} else {
   678  			print("copyu: bad %P\n", p);
   679  		}
   680  		return 0;
   681  
   682  	case ARLWMI:	/* read p->from, read p->reg, rar p->to */
   683  	case ARLWMICC:
   684  		if(copyas(&p->to, v))
   685  			return 2;
   686  		/* fall through */
   687  
   688  	case AADD:	/* read p->from, read p->reg, write p->to */
   689  	case AADDC:
   690  	case AADDE:
   691  	case ASUB:
   692  	case ASLW:
   693  	case ASRW:
   694  	case ASRAW:
   695  	case ASLD:
   696  	case ASRD:
   697  	case ASRAD:
   698  	case AOR:
   699  	case AORCC:
   700  	case AORN:
   701  	case AORNCC:
   702  	case AAND:
   703  	case AANDCC:
   704  	case AANDN:
   705  	case AANDNCC:
   706  	case ANAND:
   707  	case ANANDCC:
   708  	case ANOR:
   709  	case ANORCC:
   710  	case AXOR:
   711  	case AMULHW:
   712  	case AMULHWU:
   713  	case AMULLW:
   714  	case AMULLD:
   715  	case ADIVW:
   716  	case ADIVD:
   717  	case ADIVWU:
   718  	case ADIVDU:
   719  	case AREM:
   720  	case AREMU:
   721  	case AREMD:
   722  	case AREMDU:
   723  	case ARLWNM:
   724  	case ARLWNMCC:
   725  
   726  	case AFADDS:
   727  	case AFADD:
   728  	case AFSUBS:
   729  	case AFSUB:
   730  	case AFMULS:
   731  	case AFMUL:
   732  	case AFDIVS:
   733  	case AFDIV:
   734  		if(s != nil) {
   735  			if(copysub(&p->from, v, s, 1))
   736  				return 1;
   737  			if(copysub1(p, v, s, 1))
   738  				return 1;
   739  			// Update only indirect uses of v in p->to
   740  			if(!copyas(&p->to, v))
   741  				if(copysub(&p->to, v, s, 1))
   742  					return 1;
   743  			return 0;
   744  		}
   745  		if(copyas(&p->to, v)) {
   746  			if(p->reg == NREG)
   747  				// Fix up implicit reg (e.g., ADD
   748  				// R3,R4 -> ADD R3,R4,R4) so we can
   749  				// update reg and to separately.
   750  				p->reg = p->to.reg;
   751  			if(copyau(&p->from, v))
   752  				return 4;
   753  			if(copyau1(p, v))
   754  				return 4;
   755  			return 3;
   756  		}
   757  		if(copyau(&p->from, v))
   758  			return 1;
   759  		if(copyau1(p, v))
   760  			return 1;
   761  		if(copyau(&p->to, v))
   762  			return 1;
   763  		return 0;
   764  
   765  	case ABEQ:
   766  	case ABGT:
   767  	case ABGE:
   768  	case ABLT:
   769  	case ABLE:
   770  	case ABNE:
   771  	case ABVC:
   772  	case ABVS:
   773  		return 0;
   774  
   775  	case ACHECKNIL:	/* read p->from */
   776  	case ACMP:	/* read p->from, read p->to */
   777  	case ACMPU:
   778  	case ACMPW:
   779  	case ACMPWU:
   780  	case AFCMPO:
   781  	case AFCMPU:
   782  		if(s != nil) {
   783  			if(copysub(&p->from, v, s, 1))
   784  				return 1;
   785  			return copysub(&p->to, v, s, 1);
   786  		}
   787  		if(copyau(&p->from, v))
   788  			return 1;
   789  		if(copyau(&p->to, v))
   790  			return 1;
   791  		return 0;
   792  
   793  	case ABR:	/* read p->to */
   794  		// 9g never generates a branch to a GPR (this isn't
   795  		// even a normal instruction; liblink turns it in to a
   796  		// mov and a branch).
   797  		if(s != nil) {
   798  			if(copysub(&p->to, v, s, 1))
   799  				return 1;
   800  			return 0;
   801  		}
   802  		if(copyau(&p->to, v))
   803  			return 1;
   804  		return 0;
   805  
   806  	case ARETURN:	/* funny */
   807  		if(s != nil)
   808  			return 0;
   809  		// All registers die at this point, so claim
   810  		// everything is set (and not used).
   811  		return 3;
   812  
   813  	case ABL:	/* funny */
   814  		if(v->type == D_REG) {
   815  			if(v->reg <= REGEXT && v->reg > exregoffset)
   816  				return 2;
   817  			if(v->reg == REGARG)
   818  				return 2;
   819  		}
   820  		if(v->type == D_FREG) {
   821  			if(v->reg <= FREGEXT && v->reg > exfregoffset)
   822  				return 2;
   823  		}
   824  		if(p->from.type == D_REG && v->type == D_REG && p->from.reg == v->reg)
   825  			return 2;
   826  
   827  		if(s != nil) {
   828  			if(copysub(&p->to, v, s, 1))
   829  				return 1;
   830  			return 0;
   831  		}
   832  		if(copyau(&p->to, v))
   833  			return 4;
   834  		return 3;
   835  
   836  	case ADUFFZERO:
   837  		// R0 is zero, used by DUFFZERO, cannot be substituted.
   838  		// R3 is ptr to memory, used and set, cannot be substituted.
   839  		if(v->type == D_REG) {
   840  			if(v->reg == 0)
   841  				return 1;
   842  			if(v->reg == 3)
   843  				return 2;
   844  		}
   845  		return 0;
   846  
   847  	case ADUFFCOPY:
   848  		// R3, R4 are ptr to src, dst, used and set, cannot be substituted.
   849  		// R5 is scratch, set by DUFFCOPY, cannot be substituted.
   850  		if(v->type == D_REG) {
   851  			if(v->reg == 3 || v->reg == 4)
   852  				return 2;
   853  			if(v->reg == 5)
   854  				return 3;
   855  		}
   856  		return 0;
   857  
   858  	case ATEXT:	/* funny */
   859  		if(v->type == D_REG)
   860  			if(v->reg == REGARG)
   861  				return 3;
   862  		return 0;
   863  
   864  	case APCDATA:
   865  	case AFUNCDATA:
   866  	case AVARDEF:
   867  	case AVARKILL:
   868  		return 0;
   869  	}
   870  }
   871  
   872  int
   873  a2type(Prog *p)
   874  {
   875  	ProgInfo info;
   876  	proginfo(&info, p);
   877  	if(info.flags & (SizeB|SizeW|SizeL|SizeQ))
   878  		return D_REG;
   879  	if(info.flags & (SizeF|SizeD))
   880  		return D_FREG;
   881  	return D_NONE;
   882  }
   883  
   884  // copyas returns 1 if a and v address the same register.
   885  //
   886  // If a is the from operand, this means this operation reads the
   887  // register in v.  If a is the to operand, this means this operation
   888  // writes the register in v.
   889  static int
   890  copyas(Addr *a, Addr *v)
   891  {
   892  	if(regtyp(v))
   893  		if(a->type == v->type)
   894  		if(a->reg == v->reg)
   895  			return 1;
   896  	return 0;
   897  }
   898  
   899  // copyau returns 1 if a either directly or indirectly addresses the
   900  // same register as v.
   901  //
   902  // If a is the from operand, this means this operation reads the
   903  // register in v.  If a is the to operand, this means the operation
   904  // either reads or writes the register in v (if !copyas(a, v), then
   905  // the operation reads the register in v).
   906  static int
   907  copyau(Addr *a, Addr *v)
   908  {
   909  	if(copyas(a, v))
   910  		return 1;
   911  	if(v->type == D_REG)
   912  		if(a->type == D_OREG || (a->type == D_CONST && a->reg != NREG))
   913  			if(v->reg == a->reg)
   914  				return 1;
   915  	return 0;
   916  }
   917  
   918  // copyau1 returns 1 if p->reg references the same register as v and v
   919  // is a direct reference.
   920  static int
   921  copyau1(Prog *p, Addr *v)
   922  {
   923  	if(regtyp(v))
   924  		if(p->from.type == v->type || p->to.type == v->type)
   925  		if(p->reg == v->reg) {
   926  			// Whether p->reg is a GPR or an FPR is
   927  			// implied by the instruction (both are
   928  			// numbered from 0).  But the type should
   929  			// match v->type.  Sanity check this.
   930  			if(a2type(p) != v->type)
   931  				print("botch a2type %P\n", p);
   932  			return 1;
   933  		}
   934  	return 0;
   935  }
   936  
   937  // copysub replaces v with s in a if f!=0 or indicates it if could if f==0.
   938  // Returns 1 on failure to substitute (it always succeeds on ppc64).
   939  static int
   940  copysub(Addr *a, Addr *v, Addr *s, int f)
   941  {
   942  	if(f)
   943  	if(copyau(a, v))
   944  		a->reg = s->reg;
   945  	return 0;
   946  }
   947  
   948  // copysub1 replaces v with s in p1->reg if f!=0 or indicates if it could if f==0.
   949  // Returns 1 on failure to substitute (it always succeeds on ppc64).
   950  static int
   951  copysub1(Prog *p1, Addr *v, Addr *s, int f)
   952  {
   953  	if(f)
   954  	if(copyau1(p1, v))
   955  		p1->reg = s->reg;
   956  	return 0;
   957  }
   958  
   959  int
   960  sameaddr(Addr *a, Addr *v)
   961  {
   962  	if(a->type != v->type)
   963  		return 0;
   964  	if(regtyp(v) && a->reg == v->reg)
   965  		return 1;
   966  	if(v->type == D_AUTO || v->type == D_PARAM)
   967  		if(v->offset == a->offset)
   968  			return 1;
   969  	return 0;
   970  }
   971  
   972  int
   973  smallindir(Addr *a, Addr *reg)
   974  {
   975  	return reg->type == D_REG && a->type == D_OREG &&
   976  		a->reg == reg->reg &&
   977  		0 <= a->offset && a->offset < 4096;
   978  }
   979  
   980  int
   981  stackaddr(Addr *a)
   982  {
   983  	return a->type == D_REG && a->reg == REGSP;
   984  }