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

     1  // Inferno utils/5c/peep.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5c/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  
    32  #include <u.h>
    33  #include <libc.h>
    34  #include "gg.h"
    35  #include "opt.h"
    36  
    37  int	xtramodes(Reg*, Adr*);
    38  int	shiftprop(Reg *r);
    39  void	constprop(Adr *c1, Adr *v1, Reg *r);
    40  void	predicate(void);
    41  int	copyau1(Prog *p, Adr *v);
    42  int	isdconst(Addr *a);
    43  
    44  void
    45  peep(void)
    46  {
    47  	Reg *r, *r1, *r2;
    48  	Prog *p, *p1;
    49  	int t;
    50  
    51  	p1 = nil;
    52  /*
    53   * complete R structure
    54   */
    55  	for(r=firstr; r!=R; r=r1) {
    56  		r1 = r->link;
    57  		if(r1 == R)
    58  			break;
    59  		p = r->prog->link;
    60  		while(p != r1->prog)
    61  		switch(p->as) {
    62  		default:
    63  			r2 = rega();
    64  			r->link = r2;
    65  			r2->link = r1;
    66  
    67  			r2->prog = p;
    68  			r2->p1 = r;
    69  			r->s1 = r2;
    70  			r2->s1 = r1;
    71  			r1->p1 = r2;
    72  
    73  			r = r2;
    74  
    75  		case ADATA:
    76  		case AGLOBL:
    77  		case ANAME:
    78  		case ASIGNAME:
    79  		case ALOCALS:
    80  		case ATYPE:
    81  			p = p->link;
    82  		}
    83  	}
    84  //dumpit("begin", firstr);
    85  
    86  loop1:
    87  
    88  	t = 0;
    89  	for(r=firstr; r!=R; r=r->link) {
    90  		p = r->prog;
    91  		switch(p->as) {
    92  		case ASLL:
    93  		case ASRL:
    94  		case ASRA:
    95  			/*
    96  			 * elide shift into D_SHIFT operand of subsequent instruction
    97  			 */
    98  //			if(shiftprop(r)) {
    99  //				excise(r);
   100  //				t++;
   101  //				break;
   102  //			}
   103  			break;
   104  
   105  		case AMOVW:
   106  		case AMOVF:
   107  		case AMOVD:
   108  			if(regtyp(&p->from))
   109  			if(p->from.type == p->to.type)
   110  			if(p->scond == C_SCOND_NONE) {
   111  				if(copyprop(r)) {
   112  					excise(r);
   113  					t++;
   114  					break;
   115  				}
   116  				if(subprop(r) && copyprop(r)) {
   117  					excise(r);
   118  					t++;
   119  					break;
   120  				}
   121  			}
   122  			break;
   123  
   124  #ifdef NOTDEF
   125  			if(p->scond == C_SCOND_NONE)
   126  			if(regtyp(&p->to))
   127  			if(isdconst(&p->from)) {
   128  				constprop(&p->from, &p->to, r->s1);
   129  			}
   130  			break;
   131  #endif
   132  		}
   133  	}
   134  	if(t)
   135  		goto loop1;
   136  
   137  
   138  	for(r=firstr; r!=R; r=r->link) {
   139  		p = r->prog;
   140  		switch(p->as) {
   141  		case AEOR:
   142  			/*
   143  			 * EOR -1,x,y => MVN x,y
   144  			 */
   145  			if(isdconst(&p->from) && p->from.offset == -1) {
   146  				p->as = AMVN;
   147  				p->from.type = D_REG;
   148  				if(p->reg != NREG)
   149  					p->from.reg = p->reg;
   150  				else
   151  					p->from.reg = p->to.reg;
   152  				p->reg = NREG;
   153  			}
   154  			break;
   155  
   156  		case AMOVH:
   157  		case AMOVHU:
   158  		case AMOVB:
   159  		case AMOVBU:
   160  			/*
   161  			 * look for MOVB x,R; MOVB R,R
   162  			 */
   163  			r1 = r->link;
   164  			if(p->to.type != D_REG)
   165  				break;
   166  			if(r1 == R)
   167  				break;
   168  			p1 = r1->prog;
   169  			if(p1->as != p->as)
   170  				break;
   171  			if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
   172  				break;
   173  			if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
   174  				break;
   175  			excise(r1);
   176  			break;
   177  		}
   178  	}
   179  
   180  	for(r=firstr; r!=R; r=r->link) {
   181  		p = r->prog;
   182  		switch(p->as) {
   183  		case AMOVW:
   184  		case AMOVB:
   185  		case AMOVBU:
   186  			if(p->from.type == D_OREG && p->from.offset == 0)
   187  				xtramodes(r, &p->from);
   188  			else
   189  			if(p->to.type == D_OREG && p->to.offset == 0)
   190  				xtramodes(r, &p->to);
   191  			else
   192  				continue;
   193  			break;
   194  //		case ACMP:
   195  //			/*
   196  //			 * elide CMP $0,x if calculation of x can set condition codes
   197  //			 */
   198  //			if(isdconst(&p->from) || p->from.offset != 0)
   199  //				continue;
   200  //			r2 = r->s1;
   201  //			if(r2 == R)
   202  //				continue;
   203  //			t = r2->prog->as;
   204  //			switch(t) {
   205  //			default:
   206  //				continue;
   207  //			case ABEQ:
   208  //			case ABNE:
   209  //			case ABMI:
   210  //			case ABPL:
   211  //				break;
   212  //			case ABGE:
   213  //				t = ABPL;
   214  //				break;
   215  //			case ABLT:
   216  //				t = ABMI;
   217  //				break;
   218  //			case ABHI:
   219  //				t = ABNE;
   220  //				break;
   221  //			case ABLS:
   222  //				t = ABEQ;
   223  //				break;
   224  //			}
   225  //			r1 = r;
   226  //			do
   227  //				r1 = uniqp(r1);
   228  //			while (r1 != R && r1->prog->as == ANOP);
   229  //			if(r1 == R)
   230  //				continue;
   231  //			p1 = r1->prog;
   232  //			if(p1->to.type != D_REG)
   233  //				continue;
   234  //			if(p1->to.reg != p->reg)
   235  //			if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
   236  //				continue;
   237  //
   238  //			switch(p1->as) {
   239  //			default:
   240  //				continue;
   241  //			case AMOVW:
   242  //				if(p1->from.type != D_REG)
   243  //					continue;
   244  //			case AAND:
   245  //			case AEOR:
   246  //			case AORR:
   247  //			case ABIC:
   248  //			case AMVN:
   249  //			case ASUB:
   250  //			case ARSB:
   251  //			case AADD:
   252  //			case AADC:
   253  //			case ASBC:
   254  //			case ARSC:
   255  //				break;
   256  //			}
   257  //			p1->scond |= C_SBIT;
   258  //			r2->prog->as = t;
   259  //			excise(r);
   260  //			continue;
   261  		}
   262  	}
   263  
   264  //	predicate();
   265  }
   266  
   267  /*
   268   * uniqp returns a "unique" predecessor to instruction r.
   269   * If the instruction is the first one or has multiple
   270   * predecessors due to jump, R is returned.
   271   */
   272  Reg*
   273  uniqp(Reg *r)
   274  {
   275  	Reg *r1;
   276  
   277  	r1 = r->p1;
   278  	if(r1 == R) {
   279  		r1 = r->p2;
   280  		if(r1 == R || r1->p2link != R)
   281  			return R;
   282  	} else
   283  		if(r->p2 != R)
   284  			return R;
   285  	return r1;
   286  }
   287  
   288  Reg*
   289  uniqs(Reg *r)
   290  {
   291  	Reg *r1;
   292  
   293  	r1 = r->s1;
   294  	if(r1 == R) {
   295  		r1 = r->s2;
   296  		if(r1 == R)
   297  			return R;
   298  	} else
   299  		if(r->s2 != R)
   300  			return R;
   301  	return r1;
   302  }
   303  
   304  int
   305  regtyp(Adr *a)
   306  {
   307  
   308  	if(a->type == D_REG)
   309  		return 1;
   310  	if(a->type == D_FREG)
   311  		return 1;
   312  	return 0;
   313  }
   314  
   315  /*
   316   * the idea is to substitute
   317   * one register for another
   318   * from one MOV to another
   319   *	MOV	a, R0
   320   *	ADD	b, R0	/ no use of R1
   321   *	MOV	R0, R1
   322   * would be converted to
   323   *	MOV	a, R1
   324   *	ADD	b, R1
   325   *	MOV	R1, R0
   326   * hopefully, then the former or latter MOV
   327   * will be eliminated by copy propagation.
   328   */
   329  int
   330  subprop(Reg *r0)
   331  {
   332  	Prog *p;
   333  	Adr *v1, *v2;
   334  	Reg *r;
   335  	int t;
   336  
   337  	p = r0->prog;
   338  	v1 = &p->from;
   339  	if(!regtyp(v1))
   340  		return 0;
   341  	v2 = &p->to;
   342  	if(!regtyp(v2))
   343  		return 0;
   344  	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
   345  		if(uniqs(r) == R)
   346  			break;
   347  		p = r->prog;
   348  		switch(p->as) {
   349  		case ABL:
   350  			return 0;
   351  
   352  		case AMULLU:
   353  		case AMULA:
   354  		case AMVN:
   355  			return 0;
   356  
   357  		case ACMN:
   358  		case AADD:
   359  		case ASUB:
   360  		case ASBC:
   361  		case ARSB:
   362  		case ASLL:
   363  		case ASRL:
   364  		case ASRA:
   365  		case AORR:
   366  		case AAND:
   367  		case AEOR:
   368  		case AMUL:
   369  		case AMULU:
   370  		case ADIV:
   371  		case ADIVU:
   372  		case AMOD:
   373  		case AMODU:
   374  
   375  		case AADDD:
   376  		case AADDF:
   377  		case ASUBD:
   378  		case ASUBF:
   379  		case AMULD:
   380  		case AMULF:
   381  		case ADIVD:
   382  		case ADIVF:
   383  			if(p->to.type == v1->type)
   384  			if(p->to.reg == v1->reg)
   385  			if(p->scond == C_SCOND_NONE) {
   386  				if(p->reg == NREG)
   387  					p->reg = p->to.reg;
   388  				goto gotit;
   389  			}
   390  			break;
   391  
   392  		case AMOVF:
   393  		case AMOVD:
   394  		case AMOVW:
   395  			if(p->to.type == v1->type)
   396  			if(p->to.reg == v1->reg)
   397  			if(p->scond == C_SCOND_NONE)
   398  				goto gotit;
   399  			break;
   400  
   401  		case AMOVM:
   402  			t = 1<<v2->reg;
   403  			if((p->from.type == D_CONST && (p->from.offset&t)) ||
   404  			   (p->to.type == D_CONST && (p->to.offset&t)))
   405  				return 0;
   406  			break;
   407  		}
   408  		if(copyau(&p->from, v2) ||
   409  		   copyau1(p, v2) ||
   410  		   copyau(&p->to, v2))
   411  			break;
   412  		if(copysub(&p->from, v1, v2, 0) ||
   413  		   copysub1(p, v1, v2, 0) ||
   414  		   copysub(&p->to, v1, v2, 0))
   415  			break;
   416  	}
   417  	return 0;
   418  
   419  gotit:
   420  	copysub(&p->to, v1, v2, 1);
   421  	if(debug['P']) {
   422  		print("gotit: %D->%D\n%P", v1, v2, r->prog);
   423  		if(p->from.type == v2->type)
   424  			print(" excise");
   425  		print("\n");
   426  	}
   427  	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
   428  		p = r->prog;
   429  		copysub(&p->from, v1, v2, 1);
   430  		copysub1(p, v1, v2, 1);
   431  		copysub(&p->to, v1, v2, 1);
   432  		if(debug['P'])
   433  			print("%P\n", r->prog);
   434  	}
   435  	t = v1->reg;
   436  	v1->reg = v2->reg;
   437  	v2->reg = t;
   438  	if(debug['P'])
   439  		print("%P last\n", r->prog);
   440  	return 1;
   441  }
   442  
   443  /*
   444   * The idea is to remove redundant copies.
   445   *	v1->v2	F=0
   446   *	(use v2	s/v2/v1/)*
   447   *	set v1	F=1
   448   *	use v2	return fail
   449   *	-----------------
   450   *	v1->v2	F=0
   451   *	(use v2	s/v2/v1/)*
   452   *	set v1	F=1
   453   *	set v2	return success
   454   */
   455  int
   456  copyprop(Reg *r0)
   457  {
   458  	Prog *p;
   459  	Adr *v1, *v2;
   460  	Reg *r;
   461  
   462  	p = r0->prog;
   463  	v1 = &p->from;
   464  	v2 = &p->to;
   465  	if(copyas(v1, v2))
   466  		return 1;
   467  	for(r=firstr; r!=R; r=r->link)
   468  		r->active = 0;
   469  	return copy1(v1, v2, r0->s1, 0);
   470  }
   471  
   472  int
   473  copy1(Adr *v1, Adr *v2, Reg *r, int f)
   474  {
   475  	int t;
   476  	Prog *p;
   477  
   478  	if(r->active) {
   479  		if(debug['P'])
   480  			print("act set; return 1\n");
   481  		return 1;
   482  	}
   483  	r->active = 1;
   484  	if(debug['P'])
   485  		print("copy %D->%D f=%d\n", v1, v2, f);
   486  	for(; r != R; r = r->s1) {
   487  		p = r->prog;
   488  		if(debug['P'])
   489  			print("%P", p);
   490  		if(!f && uniqp(r) == R) {
   491  			f = 1;
   492  			if(debug['P'])
   493  				print("; merge; f=%d", f);
   494  		}
   495  		t = copyu(p, v2, A);
   496  		switch(t) {
   497  		case 2:	/* rar, cant split */
   498  			if(debug['P'])
   499  				print("; %Drar; return 0\n", v2);
   500  			return 0;
   501  
   502  		case 3:	/* set */
   503  			if(debug['P'])
   504  				print("; %Dset; return 1\n", v2);
   505  			return 1;
   506  
   507  		case 1:	/* used, substitute */
   508  		case 4:	/* use and set */
   509  			if(f) {
   510  				if(!debug['P'])
   511  					return 0;
   512  				if(t == 4)
   513  					print("; %Dused+set and f=%d; return 0\n", v2, f);
   514  				else
   515  					print("; %Dused and f=%d; return 0\n", v2, f);
   516  				return 0;
   517  			}
   518  			if(copyu(p, v2, v1)) {
   519  				if(debug['P'])
   520  					print("; sub fail; return 0\n");
   521  				return 0;
   522  			}
   523  			if(debug['P'])
   524  				print("; sub%D/%D", v2, v1);
   525  			if(t == 4) {
   526  				if(debug['P'])
   527  					print("; %Dused+set; return 1\n", v2);
   528  				return 1;
   529  			}
   530  			break;
   531  		}
   532  		if(!f) {
   533  			t = copyu(p, v1, A);
   534  			if(!f && (t == 2 || t == 3 || t == 4)) {
   535  				f = 1;
   536  				if(debug['P'])
   537  					print("; %Dset and !f; f=%d", v1, f);
   538  			}
   539  		}
   540  		if(debug['P'])
   541  			print("\n");
   542  		if(r->s2)
   543  			if(!copy1(v1, v2, r->s2, f))
   544  				return 0;
   545  	}
   546  	return 1;
   547  }
   548  
   549  /*
   550   * The idea is to remove redundant constants.
   551   *	$c1->v1
   552   *	($c1->v2 s/$c1/v1)*
   553   *	set v1  return
   554   * The v1->v2 should be eliminated by copy propagation.
   555   */
   556  void
   557  constprop(Adr *c1, Adr *v1, Reg *r)
   558  {
   559  	Prog *p;
   560  
   561  	if(debug['P'])
   562  		print("constprop %D->%D\n", c1, v1);
   563  	for(; r != R; r = r->s1) {
   564  		p = r->prog;
   565  		if(debug['P'])
   566  			print("%P", p);
   567  		if(uniqp(r) == R) {
   568  			if(debug['P'])
   569  				print("; merge; return\n");
   570  			return;
   571  		}
   572  		if(p->as == AMOVW && copyas(&p->from, c1)) {
   573  				if(debug['P'])
   574  					print("; sub%D/%D", &p->from, v1);
   575  				p->from = *v1;
   576  		} else if(copyu(p, v1, A) > 1) {
   577  			if(debug['P'])
   578  				print("; %Dset; return\n", v1);
   579  			return;
   580  		}
   581  		if(debug['P'])
   582  			print("\n");
   583  		if(r->s2)
   584  			constprop(c1, v1, r->s2);
   585  	}
   586  }
   587  
   588  /*
   589   * ASLL x,y,w
   590   * .. (not use w, not set x y w)
   591   * AXXX w,a,b (a != w)
   592   * .. (not use w)
   593   * (set w)
   594   * ----------- changed to
   595   * ..
   596   * AXXX (x<<y),a,b
   597   * ..
   598   */
   599  #define FAIL(msg) { if(debug['P']) print("\t%s; FAILURE\n", msg); return 0; }
   600  int
   601  shiftprop(Reg *r)
   602  {
   603  	Reg *r1;
   604  	Prog *p, *p1, *p2;
   605  	int n, o;
   606  	Adr a;
   607  
   608  	p = r->prog;
   609  	if(p->to.type != D_REG)
   610  		FAIL("BOTCH: result not reg");
   611  	n = p->to.reg;
   612  	a = zprog.from;
   613  	if(p->reg != NREG && p->reg != p->to.reg) {
   614  		a.type = D_REG;
   615  		a.reg = p->reg;
   616  	}
   617  	if(debug['P'])
   618  		print("shiftprop\n%P", p);
   619  	r1 = r;
   620  	for(;;) {
   621  		/* find first use of shift result; abort if shift operands or result are changed */
   622  		r1 = uniqs(r1);
   623  		if(r1 == R)
   624  			FAIL("branch");
   625  		if(uniqp(r1) == R)
   626  			FAIL("merge");
   627  		p1 = r1->prog;
   628  		if(debug['P'])
   629  			print("\n%P", p1);
   630  		switch(copyu(p1, &p->to, A)) {
   631  		case 0:	/* not used or set */
   632  			if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
   633  			   (a.type == D_REG && copyu(p1, &a, A) > 1))
   634  				FAIL("args modified");
   635  			continue;
   636  		case 3:	/* set, not used */
   637  			FAIL("BOTCH: noref");
   638  		}
   639  		break;
   640  	}
   641  	/* check whether substitution can be done */
   642  	switch(p1->as) {
   643  	default:
   644  		FAIL("non-dpi");
   645  	case AAND:
   646  	case AEOR:
   647  	case AADD:
   648  	case AADC:
   649  	case AORR:
   650  	case ASUB:
   651  	case ASBC:
   652  	case ARSB:
   653  	case ARSC:
   654  		if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {
   655  			if(p1->from.type != D_REG)
   656  				FAIL("can't swap");
   657  			p1->reg = p1->from.reg;
   658  			p1->from.reg = n;
   659  			switch(p1->as) {
   660  			case ASUB:
   661  				p1->as = ARSB;
   662  				break;
   663  			case ARSB:
   664  				p1->as = ASUB;
   665  				break;
   666  			case ASBC:
   667  				p1->as = ARSC;
   668  				break;
   669  			case ARSC:
   670  				p1->as = ASBC;
   671  				break;
   672  			}
   673  			if(debug['P'])
   674  				print("\t=>%P", p1);
   675  		}
   676  	case ABIC:
   677  	case ATST:
   678  	case ACMP:
   679  	case ACMN:
   680  		if(p1->reg == n)
   681  			FAIL("can't swap");
   682  		if(p1->reg == NREG && p1->to.reg == n)
   683  			FAIL("shift result used twice");
   684  //	case AMVN:
   685  		if(p1->from.type == D_SHIFT)
   686  			FAIL("shift result used in shift");
   687  		if(p1->from.type != D_REG || p1->from.reg != n)
   688  			FAIL("BOTCH: where is it used?");
   689  		break;
   690  	}
   691  	/* check whether shift result is used subsequently */
   692  	p2 = p1;
   693  	if(p1->to.reg != n)
   694  	for (;;) {
   695  		r1 = uniqs(r1);
   696  		if(r1 == R)
   697  			FAIL("inconclusive");
   698  		p1 = r1->prog;
   699  		if(debug['P'])
   700  			print("\n%P", p1);
   701  		switch(copyu(p1, &p->to, A)) {
   702  		case 0:	/* not used or set */
   703  			continue;
   704  		case 3: /* set, not used */
   705  			break;
   706  		default:/* used */
   707  			FAIL("reused");
   708  		}
   709  		break;
   710  	}
   711  
   712  	/* make the substitution */
   713  	p2->from.type = D_SHIFT;
   714  	p2->from.reg = NREG;
   715  	o = p->reg;
   716  	if(o == NREG)
   717  		o = p->to.reg;
   718  
   719  	switch(p->from.type){
   720  	case D_CONST:
   721  		o |= (p->from.offset&0x1f)<<7;
   722  		break;
   723  	case D_REG:
   724  		o |= (1<<4) | (p->from.reg<<8);
   725  		break;
   726  	}
   727  	switch(p->as){
   728  	case ASLL:
   729  		o |= 0<<5;
   730  		break;
   731  	case ASRL:
   732  		o |= 1<<5;
   733  		break;
   734  	case ASRA:
   735  		o |= 2<<5;
   736  		break;
   737  	}
   738  	p2->from.offset = o;
   739  	if(debug['P'])
   740  		print("\t=>%P\tSUCCEED\n", p2);
   741  	return 1;
   742  }
   743  
   744  /*
   745   * findpre returns the last instruction mentioning v
   746   * before r. It must be a set, and there must be
   747   * a unique path from that instruction to r.
   748   */
   749  Reg*
   750  findpre(Reg *r, Adr *v)
   751  {
   752  	Reg *r1;
   753  
   754  	for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
   755  		if(uniqs(r1) != r)
   756  			return R;
   757  		switch(copyu(r1->prog, v, A)) {
   758  		case 1: /* used */
   759  		case 2: /* read-alter-rewrite */
   760  			return R;
   761  		case 3: /* set */
   762  		case 4: /* set and used */
   763  			return r1;
   764  		}
   765  	}
   766  	return R;
   767  }
   768  
   769  /*
   770   * findinc finds ADD instructions with a constant
   771   * argument which falls within the immed_12 range.
   772   */
   773  Reg*
   774  findinc(Reg *r, Reg *r2, Adr *v)
   775  {
   776  	Reg *r1;
   777  	Prog *p;
   778  
   779  
   780  	for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
   781  		if(uniqp(r1) != r)
   782  			return R;
   783  		switch(copyu(r1->prog, v, A)) {
   784  		case 0: /* not touched */
   785  			continue;
   786  		case 4: /* set and used */
   787  			p = r1->prog;
   788  			if(p->as == AADD)
   789  			if(isdconst(&p->from))
   790  			if(p->from.offset > -4096 && p->from.offset < 4096)
   791  				return r1;
   792  		default:
   793  			return R;
   794  		}
   795  	}
   796  	return R;
   797  }
   798  
   799  int
   800  nochange(Reg *r, Reg *r2, Prog *p)
   801  {
   802  	Adr a[3];
   803  	int i, n;
   804  
   805  	if(r == r2)
   806  		return 1;
   807  	n = 0;
   808  	if(p->reg != NREG && p->reg != p->to.reg) {
   809  		a[n].type = D_REG;
   810  		a[n++].reg = p->reg;
   811  	}
   812  	switch(p->from.type) {
   813  	case D_SHIFT:
   814  		a[n].type = D_REG;
   815  		a[n++].reg = p->from.offset&0xf;
   816  	case D_REG:
   817  		a[n].type = D_REG;
   818  		a[n++].reg = p->from.reg;
   819  	}
   820  	if(n == 0)
   821  		return 1;
   822  	for(; r!=R && r!=r2; r=uniqs(r)) {
   823  		p = r->prog;
   824  		for(i=0; i<n; i++)
   825  			if(copyu(p, &a[i], A) > 1)
   826  				return 0;
   827  	}
   828  	return 1;
   829  }
   830  
   831  int
   832  findu1(Reg *r, Adr *v)
   833  {
   834  	for(; r != R; r = r->s1) {
   835  		if(r->active)
   836  			return 0;
   837  		r->active = 1;
   838  		switch(copyu(r->prog, v, A)) {
   839  		case 1: /* used */
   840  		case 2: /* read-alter-rewrite */
   841  		case 4: /* set and used */
   842  			return 1;
   843  		case 3: /* set */
   844  			return 0;
   845  		}
   846  		if(r->s2)
   847  			if (findu1(r->s2, v))
   848  				return 1;
   849  	}
   850  	return 0;
   851  }
   852  
   853  int
   854  finduse(Reg *r, Adr *v)
   855  {
   856  	Reg *r1;
   857  
   858  	for(r1=firstr; r1!=R; r1=r1->link)
   859  		r1->active = 0;
   860  	return findu1(r, v);
   861  }
   862  
   863  /*
   864   * xtramodes enables the ARM post increment and
   865   * shift offset addressing modes to transform
   866   *   MOVW   0(R3),R1
   867   *   ADD    $4,R3,R3
   868   * into
   869   *   MOVW.P 4(R3),R1
   870   * and 
   871   *   ADD    R0,R1
   872   *   MOVBU  0(R1),R0
   873   * into 
   874   *   MOVBU  R0<<0(R1),R0
   875   */
   876  int
   877  xtramodes(Reg *r, Adr *a)
   878  {
   879  	Reg *r1, *r2, *r3;
   880  	Prog *p, *p1;
   881  	Adr v;
   882  
   883  	p = r->prog;
   884  	v = *a;
   885  	v.type = D_REG;
   886  	r1 = findpre(r, &v);
   887  	if(r1 != R) {
   888  		p1 = r1->prog;
   889  		if(p1->to.type == D_REG && p1->to.reg == v.reg)
   890  		switch(p1->as) {
   891  		case AADD:
   892  			if(p1->scond & C_SBIT)
   893  				// avoid altering ADD.S/ADC sequences.
   894  				break;
   895  			if(p1->from.type == D_REG ||
   896  			   (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
   897  			    (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
   898  			   (p1->from.type == D_CONST &&
   899  			    p1->from.offset > -4096 && p1->from.offset < 4096))
   900  			if(nochange(uniqs(r1), r, p1)) {
   901  				if(a != &p->from || v.reg != p->to.reg)
   902  				if (finduse(r->s1, &v)) {
   903  					if(p1->reg == NREG || p1->reg == v.reg)
   904  						/* pre-indexing */
   905  						p->scond |= C_WBIT;
   906  					else return 0;
   907  				}
   908  				switch (p1->from.type) {
   909  				case D_REG:
   910  					/* register offset */
   911  					a->type = D_SHIFT;
   912  					a->offset = p1->from.reg;
   913  					break;
   914  				case D_SHIFT:
   915  					/* scaled register offset */
   916  					a->type = D_SHIFT;
   917  				case D_CONST:
   918  					/* immediate offset */
   919  					a->offset = p1->from.offset;
   920  					break;
   921  				}
   922  				if(p1->reg != NREG)
   923  					a->reg = p1->reg;
   924  				excise(r1);
   925  				return 1;
   926  			}
   927  			break;
   928  		case AMOVW:
   929  			if(p1->from.type == D_REG)
   930  			if((r2 = findinc(r1, r, &p1->from)) != R) {
   931  			for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
   932  				;
   933  			if(r3 == r) {
   934  				/* post-indexing */
   935  				p1 = r2->prog;
   936  				a->reg = p1->to.reg;
   937  				a->offset = p1->from.offset;
   938  				p->scond |= C_PBIT;
   939  				if(!finduse(r, &r1->prog->to))
   940  					excise(r1);
   941  				excise(r2);
   942  				return 1;
   943  			}
   944  			}
   945  			break;
   946  		}
   947  	}
   948  	if(a != &p->from || a->reg != p->to.reg)
   949  	if((r1 = findinc(r, R, &v)) != R) {
   950  		/* post-indexing */
   951  		p1 = r1->prog;
   952  		a->offset = p1->from.offset;
   953  		p->scond |= C_PBIT;
   954  		excise(r1);
   955  		return 1;
   956  	}
   957  	return 0;
   958  }
   959  
   960  /*
   961   * return
   962   * 1 if v only used (and substitute),
   963   * 2 if read-alter-rewrite
   964   * 3 if set
   965   * 4 if set and used
   966   * 0 otherwise (not touched)
   967   */
   968  int
   969  copyu(Prog *p, Adr *v, Adr *s)
   970  {
   971  	switch(p->as) {
   972  
   973  	default:
   974  		print("copyu: cant find %A\n", p->as);
   975  		return 2;
   976  
   977  	case AMOVM:
   978  		if(v->type != D_REG)
   979  			return 0;
   980  		if(p->from.type == D_CONST) {	/* read reglist, read/rar */
   981  			if(s != A) {
   982  				if(p->from.offset&(1<<v->reg))
   983  					return 1;
   984  				if(copysub(&p->to, v, s, 1))
   985  					return 1;
   986  				return 0;
   987  			}
   988  			if(copyau(&p->to, v)) {
   989  				if(p->scond&C_WBIT)
   990  					return 2;
   991  				return 1;
   992  			}
   993  			if(p->from.offset&(1<<v->reg))
   994  				return 1;
   995  		} else {			/* read/rar, write reglist */
   996  			if(s != A) {
   997  				if(p->to.offset&(1<<v->reg))
   998  					return 1;
   999  				if(copysub(&p->from, v, s, 1))
  1000  					return 1;
  1001  				return 0;
  1002  			}
  1003  			if(copyau(&p->from, v)) {
  1004  				if(p->scond&C_WBIT)
  1005  					return 2;
  1006  				if(p->to.offset&(1<<v->reg))
  1007  					return 4;
  1008  				return 1;
  1009  			}
  1010  			if(p->to.offset&(1<<v->reg))
  1011  				return 3;
  1012  		}
  1013  		return 0;
  1014  
  1015  	case ANOP:	/* read,, write */
  1016  	case AMOVW:
  1017  	case AMOVF:
  1018  	case AMOVD:
  1019  	case AMOVH:
  1020  	case AMOVHU:
  1021  	case AMOVB:
  1022  	case AMOVBU:
  1023  	case AMOVFW:
  1024  	case AMOVWF:
  1025  	case AMOVDW:
  1026  	case AMOVWD:
  1027  	case AMOVFD:
  1028  	case AMOVDF:
  1029  		if(p->scond&(C_WBIT|C_PBIT))
  1030  		if(v->type == D_REG) {
  1031  			if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
  1032  				if(p->from.reg == v->reg)
  1033  					return 2;
  1034  			} else {
  1035  		  		if(p->to.reg == v->reg)
  1036  					return 2;
  1037  			}
  1038  		}
  1039  		if(s != A) {
  1040  			if(copysub(&p->from, v, s, 1))
  1041  				return 1;
  1042  			if(!copyas(&p->to, v))
  1043  				if(copysub(&p->to, v, s, 1))
  1044  					return 1;
  1045  			return 0;
  1046  		}
  1047  		if(copyas(&p->to, v)) {
  1048  			if(p->scond != C_SCOND_NONE)
  1049  				return 2;
  1050  			if(copyau(&p->from, v))
  1051  				return 4;
  1052  			return 3;
  1053  		}
  1054  		if(copyau(&p->from, v))
  1055  			return 1;
  1056  		if(copyau(&p->to, v))
  1057  			return 1;
  1058  		return 0;
  1059  
  1060  	case AMULLU:	/* read, read, write, write */
  1061  	case AMULL:
  1062  	case AMULA:
  1063  	case AMVN:
  1064  		return 2;
  1065  
  1066  	case AADD:	/* read, read, write */
  1067  	case AADC:
  1068  	case ASUB:
  1069  	case ASBC:
  1070  	case ARSB:
  1071  	case ASLL:
  1072  	case ASRL:
  1073  	case ASRA:
  1074  	case AORR:
  1075  	case AAND:
  1076  	case AEOR:
  1077  	case AMUL:
  1078  	case AMULU:
  1079  	case ADIV:
  1080  	case ADIVU:
  1081  	case AMOD:
  1082  	case AMODU:
  1083  	case AADDF:
  1084  	case AADDD:
  1085  	case ASUBF:
  1086  	case ASUBD:
  1087  	case AMULF:
  1088  	case AMULD:
  1089  	case ADIVF:
  1090  	case ADIVD:
  1091  
  1092  	case ACMPF:	/* read, read, */
  1093  	case ACMPD:
  1094  	case ACMP:
  1095  	case ACMN:
  1096  	case ACASE:
  1097  	case ATST:	/* read,, */
  1098  		if(s != A) {
  1099  			if(copysub(&p->from, v, s, 1))
  1100  				return 1;
  1101  			if(copysub1(p, v, s, 1))
  1102  				return 1;
  1103  			if(!copyas(&p->to, v))
  1104  				if(copysub(&p->to, v, s, 1))
  1105  					return 1;
  1106  			return 0;
  1107  		}
  1108  		if(copyas(&p->to, v)) {
  1109  			if(p->scond != C_SCOND_NONE)
  1110  				return 2;
  1111  			if(p->reg == NREG)
  1112  				p->reg = p->to.reg;
  1113  			if(copyau(&p->from, v))
  1114  				return 4;
  1115  			if(copyau1(p, v))
  1116  				return 4;
  1117  			return 3;
  1118  		}
  1119  		if(copyau(&p->from, v))
  1120  			return 1;
  1121  		if(copyau1(p, v))
  1122  			return 1;
  1123  		if(copyau(&p->to, v))
  1124  			return 1;
  1125  		return 0;
  1126  
  1127  	case ABEQ:	/* read, read */
  1128  	case ABNE:
  1129  	case ABCS:
  1130  	case ABHS:
  1131  	case ABCC:
  1132  	case ABLO:
  1133  	case ABMI:
  1134  	case ABPL:
  1135  	case ABVS:
  1136  	case ABVC:
  1137  	case ABHI:
  1138  	case ABLS:
  1139  	case ABGE:
  1140  	case ABLT:
  1141  	case ABGT:
  1142  	case ABLE:
  1143  		if(s != A) {
  1144  			if(copysub(&p->from, v, s, 1))
  1145  				return 1;
  1146  			return copysub1(p, v, s, 1);
  1147  		}
  1148  		if(copyau(&p->from, v))
  1149  			return 1;
  1150  		if(copyau1(p, v))
  1151  			return 1;
  1152  		return 0;
  1153  
  1154  	case AB:	/* funny */
  1155  		if(s != A) {
  1156  			if(copysub(&p->to, v, s, 1))
  1157  				return 1;
  1158  			return 0;
  1159  		}
  1160  		if(copyau(&p->to, v))
  1161  			return 1;
  1162  		return 0;
  1163  
  1164  	case ARET:	/* funny */
  1165  		if(s != A)
  1166  			return 1;
  1167  		return 3;
  1168  
  1169  	case ABL:	/* funny */
  1170  		if(v->type == D_REG) {
  1171  			if(v->reg <= REGEXT && v->reg > exregoffset)
  1172  				return 2;
  1173  			if(v->reg == (uchar)REGARG)
  1174  				return 2;
  1175  		}
  1176  		if(v->type == D_FREG)
  1177  			if(v->reg <= FREGEXT && v->reg > exfregoffset)
  1178  				return 2;
  1179  		if(p->from.type == D_REG && v->type == D_REG && p->from.reg == v->reg)
  1180  			return 2;
  1181  
  1182  		if(s != A) {
  1183  			if(copysub(&p->to, v, s, 1))
  1184  				return 1;
  1185  			return 0;
  1186  		}
  1187  		if(copyau(&p->to, v))
  1188  			return 4;
  1189  		return 3;
  1190  
  1191  	case ATEXT:	/* funny */
  1192  		if(v->type == D_REG)
  1193  			if(v->reg == (uchar)REGARG)
  1194  				return 3;
  1195  		return 0;
  1196  
  1197  	case ALOCALS:	/* funny */
  1198  		return 0;
  1199  	}
  1200  }
  1201  
  1202  /*
  1203   * direct reference,
  1204   * could be set/use depending on
  1205   * semantics
  1206   */
  1207  int
  1208  copyas(Adr *a, Adr *v)
  1209  {
  1210  
  1211  	if(regtyp(v)) {
  1212  		if(a->type == v->type)
  1213  		if(a->reg == v->reg)
  1214  			return 1;
  1215  	} else
  1216  	if(v->type == D_CONST) {		/* for constprop */
  1217  		if(a->type == v->type)
  1218  		if(a->name == v->name)
  1219  		if(a->sym == v->sym)
  1220  		if(a->reg == v->reg)
  1221  		if(a->offset == v->offset)
  1222  			return 1;
  1223  	}
  1224  	return 0;
  1225  }
  1226  
  1227  /*
  1228   * either direct or indirect
  1229   */
  1230  int
  1231  copyau(Adr *a, Adr *v)
  1232  {
  1233  
  1234  	if(copyas(a, v))
  1235  		return 1;
  1236  	if(v->type == D_REG) {
  1237  		if(a->type == D_CONST && a->reg != NREG) {
  1238  			if(a->reg == v->reg)
  1239  				return 1;
  1240  		} else
  1241  		if(a->type == D_OREG) {
  1242  			if(a->reg == v->reg)
  1243  				return 1;
  1244  		} else
  1245  		if(a->type == D_REGREG || a->type == D_REGREG2) {
  1246  			if(a->reg == v->reg)
  1247  				return 1;
  1248  			if(a->offset == v->reg)
  1249  				return 1;
  1250  		} else
  1251  		if(a->type == D_SHIFT) {
  1252  			if((a->offset&0xf) == v->reg)
  1253  				return 1;
  1254  			if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
  1255  				return 1;
  1256  		}
  1257  	}
  1258  	return 0;
  1259  }
  1260  
  1261  /*
  1262   * compare v to the center
  1263   * register in p (p->reg)
  1264   * the trick is that this
  1265   * register might be D_REG
  1266   * D_FREG. there are basically
  1267   * two cases,
  1268   *	ADD r,r,r
  1269   *	CMP r,r,
  1270   */
  1271  int
  1272  copyau1(Prog *p, Adr *v)
  1273  {
  1274  
  1275  	if(regtyp(v))
  1276  	if(p->reg == v->reg) {
  1277  		if(p->to.type != D_NONE) {
  1278  			if(v->type == p->to.type)
  1279  				return 1;
  1280  			return 0;
  1281  		}
  1282  		if(p->from.type != D_NONE) {
  1283  			if(v->type == p->from.type)
  1284  				return 1;
  1285  			return 0;
  1286  		}
  1287  		print("copyau1: cant tell %P\n", p);
  1288  	}
  1289  	return 0;
  1290  }
  1291  
  1292  /*
  1293   * substitute s for v in a
  1294   * return failure to substitute
  1295   */
  1296  int
  1297  copysub(Adr *a, Adr *v, Adr *s, int f)
  1298  {
  1299  
  1300  	if(f)
  1301  	if(copyau(a, v)) {
  1302  		if(a->type == D_SHIFT) {
  1303  			if((a->offset&0xf) == v->reg)
  1304  				a->offset = (a->offset&~0xf)|s->reg;
  1305  			if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
  1306  				a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
  1307  		} else
  1308  		if(a->type == D_REGREG || a->type == D_REGREG2) {
  1309  			if(a->offset == v->reg)
  1310  				a->offset = s->reg;
  1311  			if(a->reg == v->reg)
  1312  				a->reg = s->reg;
  1313  		} else
  1314  			a->reg = s->reg;
  1315  	}
  1316  	return 0;
  1317  }
  1318  
  1319  int
  1320  copysub1(Prog *p1, Adr *v, Adr *s, int f)
  1321  {
  1322  
  1323  	if(f)
  1324  	if(copyau1(p1, v))
  1325  		p1->reg = s->reg;
  1326  	return 0;
  1327  }
  1328  
  1329  struct {
  1330  	int opcode;
  1331  	int notopcode;
  1332  	int scond;
  1333  	int notscond;
  1334  } predinfo[]  = {
  1335  	{ ABEQ,	ABNE,	0x0,	0x1, },
  1336  	{ ABNE,	ABEQ,	0x1,	0x0, },
  1337  	{ ABCS,	ABCC,	0x2,	0x3, },
  1338  	{ ABHS,	ABLO,	0x2,	0x3, },
  1339  	{ ABCC,	ABCS,	0x3,	0x2, },
  1340  	{ ABLO,	ABHS,	0x3,	0x2, },
  1341  	{ ABMI,	ABPL,	0x4,	0x5, },
  1342  	{ ABPL,	ABMI,	0x5,	0x4, },
  1343  	{ ABVS,	ABVC,	0x6,	0x7, },
  1344  	{ ABVC,	ABVS,	0x7,	0x6, },
  1345  	{ ABHI,	ABLS,	0x8,	0x9, },
  1346  	{ ABLS,	ABHI,	0x9,	0x8, },
  1347  	{ ABGE,	ABLT,	0xA,	0xB, },
  1348  	{ ABLT,	ABGE,	0xB,	0xA, },
  1349  	{ ABGT,	ABLE,	0xC,	0xD, },
  1350  	{ ABLE,	ABGT,	0xD,	0xC, },
  1351  };
  1352  
  1353  typedef struct {
  1354  	Reg *start;
  1355  	Reg *last;
  1356  	Reg *end;
  1357  	int len;
  1358  } Joininfo;
  1359  
  1360  enum {
  1361  	Join,
  1362  	Split,
  1363  	End,
  1364  	Branch,
  1365  	Setcond,
  1366  	Toolong
  1367  };
  1368  
  1369  enum {
  1370  	Falsecond,
  1371  	Truecond,
  1372  	Delbranch,
  1373  	Keepbranch
  1374  };
  1375  
  1376  int
  1377  isbranch(Prog *p)
  1378  {
  1379  	return (ABEQ <= p->as) && (p->as <= ABLE);
  1380  }
  1381  
  1382  int
  1383  predicable(Prog *p)
  1384  {
  1385  	switch(p->as) {
  1386  	case ANOP:
  1387  	case AXXX:
  1388  	case ADATA:
  1389  	case AGLOBL:
  1390  	case AGOK:
  1391  	case AHISTORY:
  1392  	case ANAME:
  1393  	case ASIGNAME:
  1394  	case ATEXT:
  1395  	case AWORD:
  1396  	case ABCASE:
  1397  	case ACASE:
  1398  		return 0;
  1399  	}
  1400  	if(isbranch(p))
  1401  		return 0;
  1402  	return 1;
  1403  }
  1404  
  1405  /*
  1406   * Depends on an analysis of the encodings performed by 5l.
  1407   * These seem to be all of the opcodes that lead to the "S" bit
  1408   * being set in the instruction encodings.
  1409   *
  1410   * C_SBIT may also have been set explicitly in p->scond.
  1411   */
  1412  int
  1413  modifiescpsr(Prog *p)
  1414  {
  1415  	switch(p->as) {
  1416  	case AMULLU:
  1417  	case AMULA:
  1418  	case AMULU:
  1419  	case ADIVU:
  1420  
  1421  	case ATEQ:
  1422  	case ACMN:
  1423  	case ATST:
  1424  	case ACMP:
  1425  	case AMUL:
  1426  	case ADIV:
  1427  	case AMOD:
  1428  	case AMODU:
  1429  	case ABL:
  1430  		return 1;
  1431  	}
  1432  	if(p->scond & C_SBIT)
  1433  		return 1;
  1434  	return 0;
  1435  }
  1436  
  1437  /*
  1438   * Find the maximal chain of instructions starting with r which could
  1439   * be executed conditionally
  1440   */
  1441  int
  1442  joinsplit(Reg *r, Joininfo *j)
  1443  {
  1444  	j->start = r;
  1445  	j->last = r;
  1446  	j->len = 0;
  1447  	do {
  1448  		if (r->p2 && (r->p1 || r->p2->p2link)) {
  1449  			j->end = r;
  1450  			return Join;
  1451  		}
  1452  		if (r->s1 && r->s2) {
  1453  			j->end = r;
  1454  			return Split;
  1455  		}
  1456  		j->last = r;
  1457  		if (r->prog->as != ANOP)
  1458  			j->len++;
  1459  		if (!r->s1 && !r->s2) {
  1460  			j->end = r->link;
  1461  			return End;
  1462  		}
  1463  		if (r->s2) {
  1464  			j->end = r->s2;
  1465  			return Branch;
  1466  		}
  1467  		if (modifiescpsr(r->prog)) {
  1468  			j->end = r->s1;
  1469  			return Setcond;
  1470  		}
  1471  		r = r->s1;
  1472  	} while (j->len < 4);
  1473  	j->end = r;
  1474  	return Toolong;
  1475  }
  1476  
  1477  Reg*
  1478  successor(Reg *r)
  1479  {
  1480  	if(r->s1)
  1481  		return r->s1;
  1482  	else
  1483  		return r->s2;
  1484  }
  1485  
  1486  void
  1487  applypred(Reg *rstart, Joininfo *j, int cond, int branch)
  1488  {
  1489  	int pred;
  1490  	Reg *r;
  1491  
  1492  	if(j->len == 0)
  1493  		return;
  1494  	if(cond == Truecond)
  1495  		pred = predinfo[rstart->prog->as - ABEQ].scond;
  1496  	else
  1497  		pred = predinfo[rstart->prog->as - ABEQ].notscond;
  1498  
  1499  	for(r = j->start;; r = successor(r)) {
  1500  		if(r->prog->as == AB) {
  1501  			if(r != j->last || branch == Delbranch)
  1502  				excise(r);
  1503  			else {
  1504  				if(cond == Truecond)
  1505  					r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
  1506  				else
  1507  					r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
  1508  			}
  1509  		}
  1510  		else
  1511  		if(predicable(r->prog))
  1512  			r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
  1513  		if(r->s1 != r->link) {
  1514  			r->s1 = r->link;
  1515  			r->link->p1 = r;
  1516  		}
  1517  		if(r == j->last)
  1518  			break;
  1519  	}
  1520  }
  1521  
  1522  void
  1523  predicate(void)
  1524  {
  1525  	Reg *r;
  1526  	int t1, t2;
  1527  	Joininfo j1, j2;
  1528  
  1529  	for(r=firstr; r!=R; r=r->link) {
  1530  		if (isbranch(r->prog)) {
  1531  			t1 = joinsplit(r->s1, &j1);
  1532  			t2 = joinsplit(r->s2, &j2);
  1533  			if(j1.last->link != j2.start)
  1534  				continue;
  1535  			if(j1.end == j2.end)
  1536  			if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
  1537  			   (t2 == Join && (t1 == Join || t1 == Setcond))) {
  1538  				applypred(r, &j1, Falsecond, Delbranch);
  1539  				applypred(r, &j2, Truecond, Delbranch);
  1540  				excise(r);
  1541  				continue;
  1542  			}
  1543  			if(t1 == End || t1 == Branch) {
  1544  				applypred(r, &j1, Falsecond, Keepbranch);
  1545  				excise(r);
  1546  				continue;
  1547  			}
  1548  		}
  1549  	}
  1550  }
  1551  
  1552  int
  1553  isdconst(Addr *a)
  1554  {
  1555  	if(a->type == D_CONST && a->reg == NREG)
  1556  		return 1;
  1557  	return 0;
  1558  }