]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/5g: factor out prog information
authorRuss Cox <rsc@golang.org>
Mon, 12 Aug 2013 17:42:23 +0000 (13:42 -0400)
committerRuss Cox <rsc@golang.org>
Mon, 12 Aug 2013 17:42:23 +0000 (13:42 -0400)
Like CL 12637051, but for 5g instead of 6g.

R=ken2
CC=golang-dev
https://golang.org/cl/12779043

src/cmd/5g/opt.h
src/cmd/5g/peep.c
src/cmd/5g/prog.c [new file with mode: 0644]
src/cmd/5g/reg.c

index af7d654deef1518934e8d1d8da6ce4a3ae6bb557..84c81c849b8b72ecafb9dc7c69f72f09b3b3045d 100644 (file)
@@ -165,3 +165,55 @@ int32      RtoB(int);
 int32  FtoB(int);
 int    BtoR(int32);
 int    BtoF(int32);
+
+/*
+ * prog.c
+ */
+typedef struct ProgInfo ProgInfo;
+struct ProgInfo
+{
+       uint32 flags; // the bits below
+};
+
+enum
+{
+       // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
+       Pseudo = 1<<1,
+       
+       // There's nothing to say about the instruction,
+       // but it's still okay to see.
+       OK = 1<<2,
+
+       // Size of right-side write, or right-side read if no write.
+       SizeB = 1<<3,
+       SizeW = 1<<4,
+       SizeL = 1<<5,
+       SizeQ = 1<<6,
+       SizeF = 1<<7, // float aka float32
+       SizeD = 1<<8, // double aka float64
+
+       // Left side: address taken, read, write.
+       LeftAddr = 1<<9,
+       LeftRead = 1<<10,
+       LeftWrite = 1<<11,
+       
+       // Register in middle; never written.
+       RegRead = 1<<12,
+       CanRegRead = 1<<13,
+       
+       // Right side: address taken, read, write.
+       RightAddr = 1<<14,
+       RightRead = 1<<15,
+       RightWrite = 1<<16,
+
+       // Instruction kinds
+       Move = 1<<17, // straight move
+       Conv = 1<<18, // size conversion
+       Cjmp = 1<<19, // conditional jump
+       Break = 1<<20, // breaks control flow (no fallthrough)
+       Call = 1<<21, // function call
+       Jump = 1<<22, // jump
+       Skip = 1<<23, // data instruction
+};
+
+void proginfo(ProgInfo*, Prog*);
index b1db361164547ed596a49329ac834f82bd675d3d..71c81ecc40f9afd83e5df29490955556fe48c417 100644 (file)
@@ -50,6 +50,7 @@ peep(void)
        Reg *r, *r1, *r2;
        Prog *p;
        int t;
+       ProgInfo info;
 
 /*
  * complete R structure
@@ -58,28 +59,24 @@ peep(void)
                r1 = r->link;
                if(r1 == R)
                        break;
-               p = r->prog->link;
-               while(p != r1->prog)
-               switch(p->as) {
-               default:
+               for(p = r->prog->link; p != r1->prog; p = p->link) {
+                       proginfo(&info, p);
+                       if(info.flags & Skip)
+                               continue;
+
                        r2 = rega();
                        r->link = r2;
                        r2->link = r1;
 
                        r2->prog = p;
+                       p->regp = r2;
+
                        r2->p1 = r;
                        r->s1 = r2;
                        r2->s1 = r1;
                        r1->p1 = r2;
 
                        r = r2;
-
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-               case ATYPE:
-                       p = p->link;
                }
        }
 //dumpit("begin", firstr);
@@ -324,6 +321,7 @@ subprop(Reg *r0)
        Adr *v1, *v2;
        Reg *r;
        int t;
+       ProgInfo info;
 
        p = r0->prog;
        v1 = &p->from;
@@ -336,68 +334,30 @@ subprop(Reg *r0)
                if(uniqs(r) == R)
                        break;
                p = r->prog;
-               switch(p->as) {
-               case ABL:
+               proginfo(&info, p);
+               if(info.flags & Call)
                        return 0;
 
+               if((info.flags & CanRegRead) && p->to.type == D_REG) {
+                       info.flags |= RegRead;
+                       info.flags &= ~(CanRegRead | RightRead);
+                       p->reg = p->to.reg;
+               }
+
+               switch(p->as) {
                case AMULLU:
                case AMULA:
                case AMVN:
                        return 0;
-
-               case ACMN:
-               case AADD:
-               case ASUB:
-               case ASBC:
-               case ARSB:
-               case ASLL:
-               case ASRL:
-               case ASRA:
-               case AORR:
-               case AAND:
-               case AEOR:
-               case AMUL:
-               case AMULU:
-               case ADIV:
-               case ADIVU:
-               case AMOD:
-               case AMODU:
-
-               case AADDD:
-               case AADDF:
-               case ASUBD:
-               case ASUBF:
-               case AMULD:
-               case AMULF:
-               case ADIVD:
-               case ADIVF:
-                       if(p->to.type == v1->type)
-                       if(p->to.reg == v1->reg)
-                       if(p->scond == C_SCOND_NONE) {
-                               if(p->reg == NREG)
-                                       p->reg = p->to.reg;
-                               goto gotit;
-                       }
-                       break;
-
-               case AMOVF:
-               case AMOVD:
-               case AMOVB:
-               case AMOVH:
-               case AMOVW:
+               }
+               
+               if((info.flags & (RightRead|RightWrite)) == RightWrite) {
                        if(p->to.type == v1->type)
                        if(p->to.reg == v1->reg)
                        if(p->scond == C_SCOND_NONE)
                                goto gotit;
-                       break;
-
-               case AMOVM:
-                       t = 1<<v2->reg;
-                       if((p->from.type == D_CONST && (p->from.offset&t)) ||
-                          (p->to.type == D_CONST && (p->to.offset&t)))
-                               return 0;
-                       break;
                }
+
                if(copyau(&p->from, v2) ||
                   copyau1(p, v2) ||
                   copyau(&p->to, v2))
diff --git a/src/cmd/5g/prog.c b/src/cmd/5g/prog.c
new file mode 100644 (file)
index 0000000..63709fb
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <libc.h>
+#include "gg.h"
+#include "opt.h"
+
+enum
+{
+       RightRdwr = RightRead | RightWrite,
+};
+
+// This table gives the basic information about instruction
+// generated by the compiler and processed in the optimizer.
+// See opt.h for bit definitions.
+//
+// Instructions not generated need not be listed.
+// As an exception to that rule, we typically write down all the
+// size variants of an operation even if we just use a subset.
+//
+// The table is formatted for 8-space tabs.
+static ProgInfo progtable[ALAST] = {
+       [ATYPE]=        {Pseudo | Skip},
+       [ATEXT]=        {Pseudo},
+       [AFUNCDATA]=    {Pseudo},
+       [APCDATA]=      {Pseudo},
+
+       // NOP is an internal no-op that also stands
+       // for USED and SET annotations, not the Intel opcode.
+       [ANOP]=         {LeftRead | RightWrite},
+       
+       // Integer.
+       [AADC]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [AADD]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [AAND]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ABIC]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ACMN]=         {SizeL | LeftRead | RightRead},
+       [ACMP]=         {SizeL | LeftRead | RightRead},
+       [ADIVU]=        {SizeL | LeftRead | RegRead | RightWrite},
+       [ADIV]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [AEOR]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [AMODU]=        {SizeL | LeftRead | RegRead | RightWrite},
+       [AMOD]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [AMULALU]=      {SizeL | LeftRead | RegRead | RightRdwr},
+       [AMULAL]=       {SizeL | LeftRead | RegRead | RightRdwr},
+       [AMULA]=        {SizeL | LeftRead | RegRead | RightRdwr},
+       [AMULU]=        {SizeL | LeftRead | RegRead | RightWrite},
+       [AMUL]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [AMULL]=        {SizeL | LeftRead | RegRead | RightWrite},
+       [AMULLU]=       {SizeL | LeftRead | RegRead | RightWrite},
+       [AMVN]=         {SizeL | LeftRead | RightWrite},
+       [AORR]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ARSB]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ARSC]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ASBC]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ASLL]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ASRA]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ASRL]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ASUB]=         {SizeL | LeftRead | RegRead | RightWrite},
+       [ATEQ]=         {SizeL | LeftRead | RightRead},
+       [ATST]=         {SizeL | LeftRead | RightRead},
+
+       // Floating point.
+       [AADDD]=        {SizeD | LeftRead | RightRdwr},
+       [AADDF]=        {SizeF | LeftRead | RightRdwr},
+       [ACMPD]=        {SizeD | LeftRead | RightRead},
+       [ACMPF]=        {SizeF | LeftRead | RightRead},
+       [ADIVD]=        {SizeD | LeftRead | RightRdwr},
+       [ADIVF]=        {SizeF | LeftRead | RightRdwr},
+       [AMULD]=        {SizeD | LeftRead | RightRdwr},
+       [AMULF]=        {SizeF | LeftRead | RightRdwr},
+       [ASUBD]=        {SizeD | LeftRead | RightRdwr},
+       [ASUBF]=        {SizeF | LeftRead | RightRdwr},
+
+       // Conversions.
+       [AMOVWD]=               {SizeD | LeftRead | RightWrite | Conv},
+       [AMOVWF]=               {SizeF | LeftRead | RightWrite | Conv},
+       [AMOVDF]=               {SizeF | LeftRead | RightWrite | Conv},
+       [AMOVDW]=               {SizeL | LeftRead | RightWrite | Conv},
+       [AMOVFD]=               {SizeD | LeftRead | RightWrite | Conv},
+       [AMOVFW]=               {SizeL | LeftRead | RightWrite | Conv},
+
+       // Moves.
+       [AMOVB]=                {SizeB | LeftRead | RightWrite | Move},
+       [AMOVD]=                {SizeD | LeftRead | RightWrite | Move},
+       [AMOVF]=                {SizeF | LeftRead | RightWrite | Move},
+       [AMOVH]=                {SizeW | LeftRead | RightWrite | Move},
+       [AMOVW]=                {SizeL | LeftRead | RightWrite | Move},
+
+       // These should be split into the two different conversions instead
+       // of overloading the one.
+       [AMOVBS]=               {SizeB | LeftRead | RightWrite | Conv},
+       [AMOVBU]=               {SizeB | LeftRead | RightWrite | Conv},
+       [AMOVHS]=               {SizeW | LeftRead | RightWrite | Conv},
+       [AMOVHU]=               {SizeW | LeftRead | RightWrite | Conv},
+       
+       // Jumps.
+       [AB]=           {Jump},
+       [ABL]=          {Call},
+       [ABEQ]=         {Cjmp},
+       [ABNE]=         {Cjmp},
+       [ABCS]=         {Cjmp},
+       [ABHS]=         {Cjmp},
+       [ABCC]=         {Cjmp},
+       [ABLO]=         {Cjmp},
+       [ABMI]=         {Cjmp},
+       [ABPL]=         {Cjmp},
+       [ABVS]=         {Cjmp},
+       [ABVC]=         {Cjmp},
+       [ABHI]=         {Cjmp},
+       [ABLS]=         {Cjmp},
+       [ABGE]=         {Cjmp},
+       [ABLT]=         {Cjmp},
+       [ABGT]=         {Cjmp},
+       [ABLE]=         {Cjmp},
+       [ARET]=         {Break},
+};
+
+void
+proginfo(ProgInfo *info, Prog *p)
+{
+       *info = progtable[p->as];
+       if(info->flags == 0)
+               fatal("unknown instruction %P", p);
+
+       if((info->flags & RegRead) && p->reg == NREG) {
+               info->flags &= ~RegRead;
+               info->flags |= CanRegRead | RightRead;
+       }
+       
+       if(((p->scond & C_SCOND) != C_SCOND_NONE) && (info->flags & RightWrite))
+               info->flags |= RightRead;
+}
index 0fa6c54b17b08cce79e77d7d0403b88faf0fd41c..368da58fe019f2c60652a02ee9af061d3b1ffb85 100644 (file)
@@ -180,7 +180,8 @@ regopt(Prog *firstp)
        int i, z, nr;
        uint32 vreg;
        Bits bit;
-       
+       ProgInfo info, info2;
+
        if(first == 0) {
                fmtinstall('Q', Qconv);
        }
@@ -243,14 +244,10 @@ regopt(Prog *firstp)
         */
        nr = 0;
        for(p=firstp; p != P; p = p->link) {
-               switch(p->as) {
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-               case ATYPE:
+               proginfo(&info, p);
+               if(info.flags & Skip)
                        continue;
-               }
+
                r = rega();
                nr++;
                if(firstr == R) {
@@ -267,10 +264,8 @@ regopt(Prog *firstp)
 
                r1 = r->p1;
                if(r1 != R) {
-                       switch(r1->prog->as) {
-                       case ARET:
-                       case AB:
-                       case ARFE:
+                       proginfo(&info2, r1->prog);
+                       if(info2.flags & Break) {
                                r->p1 = R;
                                r1->s1 = R;
                        }
@@ -280,140 +275,29 @@ regopt(Prog *firstp)
                if(p->as == ABL && p->to.type == D_EXTERN)
                        continue;
 
-               /*
-                * left side always read
-                */
-               bit = mkvar(r, &p->from);
-               for(z=0; z<BITS; z++)
-                       r->use1.b[z] |= bit.b[z];
-               
-               /*
-                * middle always read when present
-                */
-               if(p->reg != NREG) {
+               if(info.flags & LeftRead) {
+                       bit = mkvar(r, &p->from);
+                       for(z=0; z<BITS; z++)
+                               r->use1.b[z] |= bit.b[z];
+               }
+
+               if(info.flags & RegRead) {      
                        if(p->from.type != D_FREG)
                                r->use1.b[0] |= RtoB(p->reg);
                        else
                                r->use1.b[0] |= FtoB(p->reg);
                }
 
-               /*
-                * right side depends on opcode
-                */
-               bit = mkvar(r, &p->to);
-               if(bany(&bit))
-               switch(p->as) {
-               default:
-                       yyerror("reg: unknown op: %A", p->as);
-                       break;
-               
-               /*
-                * right side read
-                */
-               case ATST:
-               case ATEQ:
-               case ACMP:
-               case ACMN:
-               case ACMPD:
-               case ACMPF:
-               rightread:
-                       for(z=0; z<BITS; z++)
-                               r->use2.b[z] |= bit.b[z];
-                       break;
-                       
-               /*
-                * right side read or read+write, depending on middle
-                *      ADD x, z => z += x
-                *      ADD x, y, z  => z = x + y
-                */
-               case AADD:
-               case AAND:
-               case AEOR:
-               case ASUB:
-               case ARSB:
-               case AADC:
-               case ASBC:
-               case ARSC:
-               case AORR:
-               case ABIC:
-               case ASLL:
-               case ASRL:
-               case ASRA:
-               case AMUL:
-               case AMULU:
-               case ADIV:
-               case AMOD:
-               case AMODU:
-               case ADIVU:
-                       if(p->reg != NREG)
-                               goto rightread;
-                       // fall through
-
-               /*
-                * right side read+write
-                */
-               case AADDF:
-               case AADDD:
-               case ASUBF:
-               case ASUBD:
-               case AMULF:
-               case AMULD:
-               case ADIVF:
-               case ADIVD:
-               case AMULA:
-               case AMULAL:
-               case AMULALU:
-                       for(z=0; z<BITS; z++) {
-                               r->use2.b[z] |= bit.b[z];
-                               r->set.b[z] |= bit.b[z];
-                       }
-                       break;
-
-               /*
-                * right side write
-                */
-               case ANOP:
-               case AMOVB:
-               case AMOVBS:
-               case AMOVBU:
-               case AMOVD:
-               case AMOVDF:
-               case AMOVDW:
-               case AMOVF:
-               case AMOVFW:
-               case AMOVH:
-               case AMOVHS:
-               case AMOVHU:
-               case AMOVW:
-               case AMOVWD:
-               case AMOVWF:
-               case AMVN:
-               case AMULL:
-               case AMULLU:
-                       if((p->scond & C_SCOND) != C_SCOND_NONE)
+               if(info.flags & (RightAddr | RightRead | RightWrite)) {
+                       bit = mkvar(r, &p->to);
+                       if(info.flags & RightAddr)
+                               setaddrs(bit);
+                       if(info.flags & RightRead)
                                for(z=0; z<BITS; z++)
                                        r->use2.b[z] |= bit.b[z];
-                       for(z=0; z<BITS; z++)
-                               r->set.b[z] |= bit.b[z];
-                       break;
-
-               /*
-                * funny
-                */
-               case ABL:
-                       setaddrs(bit);
-                       break;
-               }
-
-               if(p->as == AMOVM) {
-                       z = p->to.offset;
-                       if(p->from.type == D_CONST)
-                               z = p->from.offset;
-                       for(i=0; z; i++) {
-                               if(z&1)
-                                       regbits |= RtoB(i);
-                               z >>= 1;
-                       }
+                       if(info.flags & RightWrite)
+                               for(z=0; z<BITS; z++)
+                                       r->set.b[z] |= bit.b[z];
                }
        }
        if(firstr == R)