github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/8c/peep.c (about)

     1  // Inferno utils/8c/peep.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/8c/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 "gc.h"
    32  
    33  static int
    34  needc(Prog *p)
    35  {
    36  	while(p != P) {
    37  		switch(p->as) {
    38  		case AADCL:
    39  		case ASBBL:
    40  		case ARCRL:
    41  			return 1;
    42  		case AADDL:
    43  		case ASUBL:
    44  		case AJMP:
    45  		case ARET:
    46  		case ACALL:
    47  			return 0;
    48  		default:
    49  			if(p->to.type == D_BRANCH)
    50  				return 0;
    51  		}
    52  		p = p->link;
    53  	}
    54  	return 0;
    55  }
    56  
    57  void
    58  peep(void)
    59  {
    60  	Reg *r, *r1, *r2;
    61  	Prog *p, *p1;
    62  	int t;
    63  
    64  	/*
    65  	 * complete R structure
    66  	 */
    67  	t = 0;
    68  	for(r=firstr; r!=R; r=r1) {
    69  		r1 = r->link;
    70  		if(r1 == R)
    71  			break;
    72  		p = r->prog->link;
    73  		while(p != r1->prog)
    74  		switch(p->as) {
    75  		default:
    76  			r2 = rega();
    77  			r->link = r2;
    78  			r2->link = r1;
    79  
    80  			r2->prog = p;
    81  			r2->p1 = r;
    82  			r->s1 = r2;
    83  			r2->s1 = r1;
    84  			r1->p1 = r2;
    85  
    86  			r = r2;
    87  			t++;
    88  
    89  		case ADATA:
    90  		case AGLOBL:
    91  		case ANAME:
    92  		case ASIGNAME:
    93  			p = p->link;
    94  		}
    95  	}
    96  
    97  	pc = 0;	/* speculating it won't kill */
    98  
    99  loop1:
   100  
   101  	t = 0;
   102  	for(r=firstr; r!=R; r=r->link) {
   103  		p = r->prog;
   104  		switch(p->as) {
   105  		case AMOVL:
   106  			if(regtyp(&p->to))
   107  			if(regtyp(&p->from)) {
   108  				if(copyprop(r)) {
   109  					excise(r);
   110  					t++;
   111  				}
   112  				if(subprop(r) && copyprop(r)) {
   113  					excise(r);
   114  					t++;
   115  				}
   116  			}
   117  			break;
   118  
   119  		case AMOVBLSX:
   120  		case AMOVBLZX:
   121  		case AMOVWLSX:
   122  		case AMOVWLZX:
   123  			if(regtyp(&p->to)) {
   124  				r1 = uniqs(r);
   125  				if(r1 != R) {
   126  					p1 = r1->prog;
   127  					if(p->as == p1->as && p->to.type == p1->from.type)
   128  						p1->as = AMOVL;
   129  				}
   130  			}
   131  			break;
   132  		case AADDL:
   133  		case AADDW:
   134  			if(p->from.type != D_CONST || needc(p->link))
   135  				break;
   136  			if(p->from.offset == -1){
   137  				if(p->as == AADDL)
   138  					p->as = ADECL;
   139  				else
   140  					p->as = ADECW;
   141  				p->from = zprog.from;
   142  			}
   143  			else if(p->from.offset == 1){
   144  				if(p->as == AADDL)
   145  					p->as = AINCL;
   146  				else
   147  					p->as = AINCW;
   148  				p->from = zprog.from;
   149  			}
   150  			break;
   151  		case ASUBL:
   152  		case ASUBW:
   153  			if(p->from.type != D_CONST || needc(p->link))
   154  				break;
   155  			if(p->from.offset == -1) {
   156  				if(p->as == ASUBL)
   157  					p->as = AINCL;
   158  				else
   159  					p->as = AINCW;
   160  				p->from = zprog.from;
   161  			}
   162  			else if(p->from.offset == 1){
   163  				if(p->as == ASUBL)
   164  					p->as = ADECL;
   165  				else
   166  					p->as = ADECW;
   167  				p->from = zprog.from;
   168  			}
   169  			break;
   170  		}
   171  	}
   172  	if(t)
   173  		goto loop1;
   174  }
   175  
   176  void
   177  excise(Reg *r)
   178  {
   179  	Prog *p;
   180  
   181  	p = r->prog;
   182  	p->as = ANOP;
   183  	p->from = zprog.from;
   184  	p->to = zprog.to;
   185  }
   186  
   187  Reg*
   188  uniqp(Reg *r)
   189  {
   190  	Reg *r1;
   191  
   192  	r1 = r->p1;
   193  	if(r1 == R) {
   194  		r1 = r->p2;
   195  		if(r1 == R || r1->p2link != R)
   196  			return R;
   197  	} else
   198  		if(r->p2 != R)
   199  			return R;
   200  	return r1;
   201  }
   202  
   203  Reg*
   204  uniqs(Reg *r)
   205  {
   206  	Reg *r1;
   207  
   208  	r1 = r->s1;
   209  	if(r1 == R) {
   210  		r1 = r->s2;
   211  		if(r1 == R)
   212  			return R;
   213  	} else
   214  		if(r->s2 != R)
   215  			return R;
   216  	return r1;
   217  }
   218  
   219  int
   220  regtyp(Adr *a)
   221  {
   222  	int t;
   223  
   224  	t = a->type;
   225  	if(t >= D_AX && t <= D_DI)
   226  		return 1;
   227  	return 0;
   228  }
   229  
   230  /*
   231   * the idea is to substitute
   232   * one register for another
   233   * from one MOV to another
   234   *	MOV	a, R0
   235   *	ADD	b, R0	/ no use of R1
   236   *	MOV	R0, R1
   237   * would be converted to
   238   *	MOV	a, R1
   239   *	ADD	b, R1
   240   *	MOV	R1, R0
   241   * hopefully, then the former or latter MOV
   242   * will be eliminated by copy propagation.
   243   */
   244  int
   245  subprop(Reg *r0)
   246  {
   247  	Prog *p;
   248  	Adr *v1, *v2;
   249  	Reg *r;
   250  	int t;
   251  
   252  	p = r0->prog;
   253  	v1 = &p->from;
   254  	if(!regtyp(v1))
   255  		return 0;
   256  	v2 = &p->to;
   257  	if(!regtyp(v2))
   258  		return 0;
   259  	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
   260  		if(uniqs(r) == R)
   261  			break;
   262  		p = r->prog;
   263  		switch(p->as) {
   264  		case ACALL:
   265  			return 0;
   266  
   267  		case AIMULL:
   268  		case AIMULW:
   269  			if(p->to.type != D_NONE)
   270  				break;
   271  
   272  		case ADIVB:
   273  		case ADIVL:
   274  		case ADIVW:
   275  		case AIDIVB:
   276  		case AIDIVL:
   277  		case AIDIVW:
   278  		case AIMULB:
   279  		case AMULB:
   280  		case AMULL:
   281  		case AMULW:
   282  
   283  		case AROLB:
   284  		case AROLL:
   285  		case AROLW:
   286  		case ARORB:
   287  		case ARORL:
   288  		case ARORW:
   289  		case ASALB:
   290  		case ASALL:
   291  		case ASALW:
   292  		case ASARB:
   293  		case ASARL:
   294  		case ASARW:
   295  		case ASHLB:
   296  		case ASHLL:
   297  		case ASHLW:
   298  		case ASHRB:
   299  		case ASHRL:
   300  		case ASHRW:
   301  
   302  		case AREP:
   303  		case AREPN:
   304  
   305  		case ACWD:
   306  		case ACDQ:
   307  
   308  		case ASTOSB:
   309  		case ASTOSL:
   310  		case AMOVSB:
   311  		case AMOVSL:
   312  		case AFSTSW:
   313  			return 0;
   314  
   315  		case AMOVL:
   316  			if(p->to.type == v1->type)
   317  				goto gotit;
   318  			break;
   319  		}
   320  		if(copyau(&p->from, v2) ||
   321  		   copyau(&p->to, v2))
   322  			break;
   323  		if(copysub(&p->from, v1, v2, 0) ||
   324  		   copysub(&p->to, v1, v2, 0))
   325  			break;
   326  	}
   327  	return 0;
   328  
   329  gotit:
   330  	copysub(&p->to, v1, v2, 1);
   331  	if(debug['P']) {
   332  		print("gotit: %D->%D\n%P", v1, v2, r->prog);
   333  		if(p->from.type == v2->type)
   334  			print(" excise");
   335  		print("\n");
   336  	}
   337  	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
   338  		p = r->prog;
   339  		copysub(&p->from, v1, v2, 1);
   340  		copysub(&p->to, v1, v2, 1);
   341  		if(debug['P'])
   342  			print("%P\n", r->prog);
   343  	}
   344  	t = v1->type;
   345  	v1->type = v2->type;
   346  	v2->type = t;
   347  	if(debug['P'])
   348  		print("%P last\n", r->prog);
   349  	return 1;
   350  }
   351  
   352  /*
   353   * The idea is to remove redundant copies.
   354   *	v1->v2	F=0
   355   *	(use v2	s/v2/v1/)*
   356   *	set v1	F=1
   357   *	use v2	return fail
   358   *	-----------------
   359   *	v1->v2	F=0
   360   *	(use v2	s/v2/v1/)*
   361   *	set v1	F=1
   362   *	set v2	return success
   363   */
   364  int
   365  copyprop(Reg *r0)
   366  {
   367  	Prog *p;
   368  	Adr *v1, *v2;
   369  	Reg *r;
   370  
   371  	p = r0->prog;
   372  	v1 = &p->from;
   373  	v2 = &p->to;
   374  	if(copyas(v1, v2))
   375  		return 1;
   376  	for(r=firstr; r!=R; r=r->link)
   377  		r->active = 0;
   378  	return copy1(v1, v2, r0->s1, 0);
   379  }
   380  
   381  int
   382  copy1(Adr *v1, Adr *v2, Reg *r, int f)
   383  {
   384  	int t;
   385  	Prog *p;
   386  
   387  	if(r->active) {
   388  		if(debug['P'])
   389  			print("act set; return 1\n");
   390  		return 1;
   391  	}
   392  	r->active = 1;
   393  	if(debug['P'])
   394  		print("copy %D->%D f=%d\n", v1, v2, f);
   395  	for(; r != R; r = r->s1) {
   396  		p = r->prog;
   397  		if(debug['P'])
   398  			print("%P", p);
   399  		if(!f && uniqp(r) == R) {
   400  			f = 1;
   401  			if(debug['P'])
   402  				print("; merge; f=%d", f);
   403  		}
   404  		t = copyu(p, v2, A);
   405  		switch(t) {
   406  		case 2:	/* rar, can't split */
   407  			if(debug['P'])
   408  				print("; %D rar; return 0\n", v2);
   409  			return 0;
   410  
   411  		case 3:	/* set */
   412  			if(debug['P'])
   413  				print("; %D set; return 1\n", v2);
   414  			return 1;
   415  
   416  		case 1:	/* used, substitute */
   417  		case 4:	/* use and set */
   418  			if(f) {
   419  				if(!debug['P'])
   420  					return 0;
   421  				if(t == 4)
   422  					print("; %D used+set and f=%d; return 0\n", v2, f);
   423  				else
   424  					print("; %D used and f=%d; return 0\n", v2, f);
   425  				return 0;
   426  			}
   427  			if(copyu(p, v2, v1)) {
   428  				if(debug['P'])
   429  					print("; sub fail; return 0\n");
   430  				return 0;
   431  			}
   432  			if(debug['P'])
   433  				print("; sub %D/%D", v2, v1);
   434  			if(t == 4) {
   435  				if(debug['P'])
   436  					print("; %D used+set; return 1\n", v2);
   437  				return 1;
   438  			}
   439  			break;
   440  		}
   441  		if(!f) {
   442  			t = copyu(p, v1, A);
   443  			if(!f && (t == 2 || t == 3 || t == 4)) {
   444  				f = 1;
   445  				if(debug['P'])
   446  					print("; %D set and !f; f=%d", v1, f);
   447  			}
   448  		}
   449  		if(debug['P'])
   450  			print("\n");
   451  		if(r->s2)
   452  			if(!copy1(v1, v2, r->s2, f))
   453  				return 0;
   454  	}
   455  	return 1;
   456  }
   457  
   458  /*
   459   * return
   460   * 1 if v only used (and substitute),
   461   * 2 if read-alter-rewrite
   462   * 3 if set
   463   * 4 if set and used
   464   * 0 otherwise (not touched)
   465   */
   466  int
   467  copyu(Prog *p, Adr *v, Adr *s)
   468  {
   469  
   470  	switch(p->as) {
   471  
   472  	default:
   473  		if(debug['P'])
   474  			print("unknown op %A\n", p->as);
   475  		return 2;
   476  
   477  	case ANEGB:
   478  	case ANEGW:
   479  	case ANEGL:
   480  	case ANOTB:
   481  	case ANOTW:
   482  	case ANOTL:
   483  		if(copyas(&p->to, v))
   484  			return 2;
   485  		break;
   486  
   487  	case ALEAL:	/* lhs addr, rhs store */
   488  		if(copyas(&p->from, v))
   489  			return 2;
   490  
   491  
   492  	case ANOP:	/* rhs store */
   493  	case AMOVL:
   494  	case AMOVBLSX:
   495  	case AMOVBLZX:
   496  	case AMOVWLSX:
   497  	case AMOVWLZX:
   498  		if(copyas(&p->to, v)) {
   499  			if(s != A)
   500  				return copysub(&p->from, v, s, 1);
   501  			if(copyau(&p->from, v))
   502  				return 4;
   503  			return 3;
   504  		}
   505  		goto caseread;
   506  
   507  	case AROLB:
   508  	case AROLL:
   509  	case AROLW:
   510  	case ARORB:
   511  	case ARORL:
   512  	case ARORW:
   513  	case ASALB:
   514  	case ASALL:
   515  	case ASALW:
   516  	case ASARB:
   517  	case ASARL:
   518  	case ASARW:
   519  	case ASHLB:
   520  	case ASHLL:
   521  	case ASHLW:
   522  	case ASHRB:
   523  	case ASHRL:
   524  	case ASHRW:
   525  		if(copyas(&p->to, v))
   526  			return 2;
   527  		if(copyas(&p->from, v))
   528  			if(p->from.type == D_CX)
   529  				return 2;
   530  		goto caseread;
   531  
   532  	case AADDB:	/* rhs rar */
   533  	case AADDL:
   534  	case AADDW:
   535  	case AANDB:
   536  	case AANDL:
   537  	case AANDW:
   538  	case ADECL:
   539  	case ADECW:
   540  	case AINCL:
   541  	case AINCW:
   542  	case ASUBB:
   543  	case ASUBL:
   544  	case ASUBW:
   545  	case AORB:
   546  	case AORL:
   547  	case AORW:
   548  	case AXORB:
   549  	case AXORL:
   550  	case AXORW:
   551  	case AMOVB:
   552  	case AMOVW:
   553  
   554  	case AFMOVB:
   555  	case AFMOVBP:
   556  	case AFMOVD:
   557  	case AFMOVDP:
   558  	case AFMOVF:
   559  	case AFMOVFP:
   560  	case AFMOVL:
   561  	case AFMOVLP:
   562  	case AFMOVV:
   563  	case AFMOVVP:
   564  	case AFMOVW:
   565  	case AFMOVWP:
   566  	case AFMOVX:
   567  	case AFMOVXP:
   568  	case AFADDDP:
   569  	case AFADDW:
   570  	case AFADDL:
   571  	case AFADDF:
   572  	case AFADDD:
   573  	case AFMULDP:
   574  	case AFMULW:
   575  	case AFMULL:
   576  	case AFMULF:
   577  	case AFMULD:
   578  	case AFSUBDP:
   579  	case AFSUBW:
   580  	case AFSUBL:
   581  	case AFSUBF:
   582  	case AFSUBD:
   583  	case AFSUBRDP:
   584  	case AFSUBRW:
   585  	case AFSUBRL:
   586  	case AFSUBRF:
   587  	case AFSUBRD:
   588  	case AFDIVDP:
   589  	case AFDIVW:
   590  	case AFDIVL:
   591  	case AFDIVF:
   592  	case AFDIVD:
   593  	case AFDIVRDP:
   594  	case AFDIVRW:
   595  	case AFDIVRL:
   596  	case AFDIVRF:
   597  	case AFDIVRD:
   598  		if(copyas(&p->to, v))
   599  			return 2;
   600  		goto caseread;
   601  
   602  	case ACMPL:	/* read only */
   603  	case ACMPW:
   604  	case ACMPB:
   605  	
   606  	case APREFETCHT0:
   607  	case APREFETCHT1:
   608  	case APREFETCHT2:
   609  	case APREFETCHNTA:
   610  
   611  
   612  	case AFCOMB:
   613  	case AFCOMBP:
   614  	case AFCOMD:
   615  	case AFCOMDP:
   616  	case AFCOMDPP:
   617  	case AFCOMF:
   618  	case AFCOMFP:
   619  	case AFCOML:
   620  	case AFCOMLP:
   621  	case AFCOMW:
   622  	case AFCOMWP:
   623  	case AFUCOM:
   624  	case AFUCOMP:
   625  	case AFUCOMPP:
   626  	caseread:
   627  		if(s != A) {
   628  			if(copysub(&p->from, v, s, 1))
   629  				return 1;
   630  			return copysub(&p->to, v, s, 1);
   631  		}
   632  		if(copyau(&p->from, v))
   633  			return 1;
   634  		if(copyau(&p->to, v))
   635  			return 1;
   636  		break;
   637  
   638  	case AJGE:	/* no reference */
   639  	case AJNE:
   640  	case AJLE:
   641  	case AJEQ:
   642  	case AJHI:
   643  	case AJLS:
   644  	case AJMI:
   645  	case AJPL:
   646  	case AJGT:
   647  	case AJLT:
   648  	case AJCC:
   649  	case AJCS:
   650  
   651  	case AADJSP:
   652  	case AFLDZ:
   653  	case AWAIT:
   654  		break;
   655  
   656  	case AIMULL:
   657  	case AIMULW:
   658  		if(p->to.type != D_NONE) {
   659  			if(copyas(&p->to, v))
   660  				return 2;
   661  			goto caseread;
   662  		}
   663  
   664  	case ADIVB:
   665  	case ADIVL:
   666  	case ADIVW:
   667  	case AIDIVB:
   668  	case AIDIVL:
   669  	case AIDIVW:
   670  	case AIMULB:
   671  	case AMULB:
   672  	case AMULL:
   673  	case AMULW:
   674  
   675  	case ACWD:
   676  	case ACDQ:
   677  		if(v->type == D_AX || v->type == D_DX)
   678  			return 2;
   679  		goto caseread;
   680  
   681  	case AREP:
   682  	case AREPN:
   683  		if(v->type == D_CX)
   684  			return 2;
   685  		goto caseread;
   686  
   687  	case AMOVSB:
   688  	case AMOVSL:
   689  		if(v->type == D_DI || v->type == D_SI)
   690  			return 2;
   691  		goto caseread;
   692  
   693  	case ASTOSB:
   694  	case ASTOSL:
   695  		if(v->type == D_AX || v->type == D_DI)
   696  			return 2;
   697  		goto caseread;
   698  
   699  	case AFSTSW:
   700  		if(v->type == D_AX)
   701  			return 2;
   702  		goto caseread;
   703  
   704  	case AJMP:	/* funny */
   705  		if(s != A) {
   706  			if(copysub(&p->to, v, s, 1))
   707  				return 1;
   708  			return 0;
   709  		}
   710  		if(copyau(&p->to, v))
   711  			return 1;
   712  		return 0;
   713  
   714  	case ARET:	/* funny */
   715  		if(v->type == REGRET)
   716  			return 2;
   717  		if(s != A)
   718  			return 1;
   719  		return 3;
   720  
   721  	case ACALL:	/* funny */
   722  		if(REGARG >= 0 && v->type == (uchar)REGARG)
   723  			return 2;
   724  
   725  		if(s != A) {
   726  			if(copysub(&p->to, v, s, 1))
   727  				return 1;
   728  			return 0;
   729  		}
   730  		if(copyau(&p->to, v))
   731  			return 4;
   732  		return 3;
   733  	}
   734  	return 0;
   735  }
   736  
   737  /*
   738   * direct reference,
   739   * could be set/use depending on
   740   * semantics
   741   */
   742  int
   743  copyas(Adr *a, Adr *v)
   744  {
   745  	if(a->type != v->type)
   746  		return 0;
   747  	if(regtyp(v))
   748  		return 1;
   749  	if(v->type == D_AUTO || v->type == D_PARAM)
   750  		if(v->offset == a->offset)
   751  			return 1;
   752  	return 0;
   753  }
   754  
   755  /*
   756   * either direct or indirect
   757   */
   758  int
   759  copyau(Adr *a, Adr *v)
   760  {
   761  
   762  	if(copyas(a, v))
   763  		return 1;
   764  	if(regtyp(v)) {
   765  		if(a->type-D_INDIR == v->type)
   766  			return 1;
   767  		if(a->index == v->type)
   768  			return 1;
   769  	}
   770  	return 0;
   771  }
   772  
   773  /*
   774   * substitute s for v in a
   775   * return failure to substitute
   776   */
   777  int
   778  copysub(Adr *a, Adr *v, Adr *s, int f)
   779  {
   780  	int t;
   781  
   782  	if(copyas(a, v)) {
   783  		t = s->type;
   784  		if(t >= D_AX && t <= D_DI) {
   785  			if(f)
   786  				a->type = t;
   787  		}
   788  		return 0;
   789  	}
   790  	if(regtyp(v)) {
   791  		t = v->type;
   792  		if(a->type == t+D_INDIR) {
   793  			if(s->type == D_BP && a->index != D_NONE)
   794  				return 1;	/* can't use BP-base with index */
   795  			if(f)
   796  				a->type = s->type+D_INDIR;
   797  //			return 0;
   798  		}
   799  		if(a->index == t) {
   800  			if(f)
   801  				a->index = s->type;
   802  			return 0;
   803  		}
   804  		return 0;
   805  	}
   806  	return 0;
   807  }