]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.cc] 9g: fill progtable for CC, V, and VCC instruction variants
authorAustin Clements <austin@google.com>
Mon, 24 Nov 2014 16:40:36 +0000 (11:40 -0500)
committerAustin Clements <austin@google.com>
Mon, 24 Nov 2014 16:40:36 +0000 (11:40 -0500)
This adds some utilities for converting between the CC, V, and
VCC variants of operations and uses these to derive the
ProgInfo entries for these variants (which are identical to
the ProgInfo for the base operations).

The 9g peephole optimizer will also use these conversion
utilities.

LGTM=minux, rsc
R=rsc, dave, minux
CC=golang-codereviews
https://golang.org/cl/180110044

src/cmd/9g/opt.h
src/cmd/9g/prog.c

index 7f15b5a69f3f70551b06230874c6786c47013218..6a07b268f212d7866ec81f03fe68ad9acc4b17e2 100644 (file)
@@ -225,6 +225,16 @@ enum
 
 void proginfo(ProgInfo*, Prog*);
 
+// Many Power ISA arithmetic and logical instructions come in four
+// standard variants.  These bits let us map between variants.
+enum {
+       V_CC = 1<<0,            // xCC (affect CR field 0 flags)
+       V_V  = 1<<1,            // xV (affect SO and OV flags)
+};
+
+int as2variant(int);
+int variant2as(int, int);
+
 // To allow use of AJMP, ACALL, ARET in ../gc/popt.c.
 enum
 {
index 51c132d183d1b5172d537e1a0bc1ff2082de80fd..7c0f0c7959e8913400c1532602ca57375e2650d5 100644 (file)
@@ -101,9 +101,36 @@ static ProgInfo progtable[ALAST] = {
        [ADUFFCOPY]=    {Call},
 };
 
+static void
+initproginfo(void)
+{
+       static int initialized;
+       int addvariant[] = {V_CC, V_V, V_CC|V_V};
+       int as, as2, i, variant;
+
+       if(initialized)
+               return;
+       initialized = 1;
+
+       // Perform one-time expansion of instructions in progtable to
+       // their CC, V, and VCC variants
+       for(as=0; as<nelem(progtable); as++) {
+               if(progtable[as].flags == 0)
+                       continue;
+               variant = as2variant(as);
+               for(i=0; i<nelem(addvariant); i++) {
+                       as2 = variant2as(as, variant | addvariant[i]);
+                       if(as2 != 0 && progtable[as2].flags == 0)
+                               progtable[as2] = progtable[as];
+               }
+       }
+}
+
 void
 proginfo(ProgInfo *info, Prog *p)
 {
+       initproginfo();
+
        *info = progtable[p->as];
        if(info->flags == 0) {
                *info = progtable[AADD];
@@ -143,3 +170,138 @@ proginfo(ProgInfo *info, Prog *p)
                info->regset |= RtoB(3) | RtoB(4);
        }
 }
+
+// Instruction variants table.  Initially this contains entries only
+// for the "base" form of each instruction.  On the first call to
+// as2variant or variant2as, we'll add the variants to the table.
+static int varianttable[ALAST][4] = {
+       [AADD]=         {AADD,          AADDCC,         AADDV,          AADDVCC},
+       [AADDC]=        {AADDC,         AADDCCC,        AADDCV,         AADDCVCC},
+       [AADDE]=        {AADDE,         AADDECC,        AADDEV,         AADDEVCC},
+       [AADDME]=       {AADDME,        AADDMECC,       AADDMEV,        AADDMEVCC},
+       [AADDZE]=       {AADDZE,        AADDZECC,       AADDZEV,        AADDZEVCC},
+       [AAND]=         {AAND,          AANDCC,         0,              0},
+       [AANDN]=        {AANDN,         AANDNCC,        0,              0},
+       [ACNTLZD]=      {ACNTLZD,       ACNTLZDCC,      0,              0},
+       [ACNTLZW]=      {ACNTLZW,       ACNTLZWCC,      0,              0},
+       [ADIVD]=        {ADIVD,         ADIVDCC,        ADIVDV,         ADIVDVCC},
+       [ADIVDU]=       {ADIVDU,        ADIVDUCC,       ADIVDUV,        ADIVDUVCC},
+       [ADIVW]=        {ADIVW,         ADIVWCC,        ADIVWV,         ADIVWVCC},
+       [ADIVWU]=       {ADIVWU,        ADIVWUCC,       ADIVWUV,        ADIVWUVCC},
+       [AEQV]=         {AEQV,          AEQVCC,         0,              0},
+       [AEXTSB]=       {AEXTSB,        AEXTSBCC,       0,              0},
+       [AEXTSH]=       {AEXTSH,        AEXTSHCC,       0,              0},
+       [AEXTSW]=       {AEXTSW,        AEXTSWCC,       0,              0},
+       [AFABS]=        {AFABS,         AFABSCC,        0,              0},
+       [AFADD]=        {AFADD,         AFADDCC,        0,              0},
+       [AFADDS]=       {AFADDS,        AFADDSCC,       0,              0},
+       [AFCFID]=       {AFCFID,        AFCFIDCC,       0,              0},
+       [AFCTID]=       {AFCTID,        AFCTIDCC,       0,              0},
+       [AFCTIDZ]=      {AFCTIDZ,       AFCTIDZCC,      0,              0},
+       [AFCTIW]=       {AFCTIW,        AFCTIWCC,       0,              0},
+       [AFCTIWZ]=      {AFCTIWZ,       AFCTIWZCC,      0,              0},
+       [AFDIV]=        {AFDIV,         AFDIVCC,        0,              0},
+       [AFDIVS]=       {AFDIVS,        AFDIVSCC,       0,              0},
+       [AFMADD]=       {AFMADD,        AFMADDCC,       0,              0},
+       [AFMADDS]=      {AFMADDS,       AFMADDSCC,      0,              0},
+       [AFMOVD]=       {AFMOVD,        AFMOVDCC,       0,              0},
+       [AFMSUB]=       {AFMSUB,        AFMSUBCC,       0,              0},
+       [AFMSUBS]=      {AFMSUBS,       AFMSUBSCC,      0,              0},
+       [AFMUL]=        {AFMUL,         AFMULCC,        0,              0},
+       [AFMULS]=       {AFMULS,        AFMULSCC,       0,              0},
+       [AFNABS]=       {AFNABS,        AFNABSCC,       0,              0},
+       [AFNEG]=        {AFNEG,         AFNEGCC,        0,              0},
+       [AFNMADD]=      {AFNMADD,       AFNMADDCC,      0,              0},
+       [AFNMADDS]=     {AFNMADDS,      AFNMADDSCC,     0,              0},
+       [AFNMSUB]=      {AFNMSUB,       AFNMSUBCC,      0,              0},
+       [AFNMSUBS]=     {AFNMSUBS,      AFNMSUBSCC,     0,              0},
+       [AFRES]=        {AFRES,         AFRESCC,        0,              0},
+       [AFRSP]=        {AFRSP,         AFRSPCC,        0,              0},
+       [AFRSQRTE]=     {AFRSQRTE,      AFRSQRTECC,     0,              0},
+       [AFSEL]=        {AFSEL,         AFSELCC,        0,              0},
+       [AFSQRT]=       {AFSQRT,        AFSQRTCC,       0,              0},
+       [AFSQRTS]=      {AFSQRTS,       AFSQRTSCC,      0,              0},
+       [AFSUB]=        {AFSUB,         AFSUBCC,        0,              0},
+       [AFSUBS]=       {AFSUBS,        AFSUBSCC,       0,              0},
+       [AMTFSB0]=      {AMTFSB0,       AMTFSB0CC,      0,              0},
+       [AMTFSB1]=      {AMTFSB1,       AMTFSB1CC,      0,              0},
+       [AMULHD]=       {AMULHD,        AMULHDCC,       0,              0},
+       [AMULHDU]=      {AMULHDU,       AMULHDUCC,      0,              0},
+       [AMULHW]=       {AMULHW,        AMULHWCC,       0,              0},
+       [AMULHWU]=      {AMULHWU,       AMULHWUCC,      0,              0},
+       [AMULLD]=       {AMULLD,        AMULLDCC,       AMULLDV,        AMULLDVCC},
+       [AMULLW]=       {AMULLW,        AMULLWCC,       AMULLWV,        AMULLWVCC},
+       [ANAND]=        {ANAND,         ANANDCC,        0,              0},
+       [ANEG]=         {ANEG,          ANEGCC,         ANEGV,          ANEGVCC},
+       [ANOR]=         {ANOR,          ANORCC,         0,              0},
+       [AOR]=          {AOR,           AORCC,          0,              0},
+       [AORN]=         {AORN,          AORNCC,         0,              0},
+       [AREM]=         {AREM,          AREMCC,         AREMV,          AREMVCC},
+       [AREMD]=        {AREMD,         AREMDCC,        AREMDV,         AREMDVCC},
+       [AREMDU]=       {AREMDU,        AREMDUCC,       AREMDUV,        AREMDUVCC},
+       [AREMU]=        {AREMU,         AREMUCC,        AREMUV,         AREMUVCC},
+       [ARLDC]=        {ARLDC,         ARLDCCC,        0,              0},
+       [ARLDCL]=       {ARLDCL,        ARLDCLCC,       0,              0},
+       [ARLDCR]=       {ARLDCR,        ARLDCRCC,       0,              0},
+       [ARLDMI]=       {ARLDMI,        ARLDMICC,       0,              0},
+       [ARLWMI]=       {ARLWMI,        ARLWMICC,       0,              0},
+       [ARLWNM]=       {ARLWNM,        ARLWNMCC,       0,              0},
+       [ASLD]=         {ASLD,          ASLDCC,         0,              0},
+       [ASLW]=         {ASLW,          ASLWCC,         0,              0},
+       [ASRAD]=        {ASRAD,         ASRADCC,        0,              0},
+       [ASRAW]=        {ASRAW,         ASRAWCC,        0,              0},
+       [ASRD]=         {ASRD,          ASRDCC,         0,              0},
+       [ASRW]=         {ASRW,          ASRWCC,         0,              0},
+       [ASUB]=         {ASUB,          ASUBCC,         ASUBV,          ASUBVCC},
+       [ASUBC]=        {ASUBC,         ASUBCCC,        ASUBCV,         ASUBCVCC},
+       [ASUBE]=        {ASUBE,         ASUBECC,        ASUBEV,         ASUBEVCC},
+       [ASUBME]=       {ASUBME,        ASUBMECC,       ASUBMEV,        ASUBMEVCC},
+       [ASUBZE]=       {ASUBZE,        ASUBZECC,       ASUBZEV,        ASUBZEVCC},
+       [AXOR]=         {AXOR,          AXORCC,         0,              0},
+};
+
+static void
+initvariants(void)
+{
+       static int initialized;
+       int i, j;
+
+       if(initialized)
+               return;
+       initialized = 1;
+
+       for(i=0; i<nelem(varianttable); i++) {
+               if(varianttable[i][0] == 0) {
+                       // Instruction has no variants
+                       varianttable[i][0] = i;
+                       continue;
+               }
+               // Copy base form to other variants
+               if(varianttable[i][0] == i) {
+                       for(j=0; j<nelem(varianttable[i]); j++)
+                               memmove(&varianttable[varianttable[i][j]], &varianttable[i], sizeof(varianttable[i]));
+               }
+       }
+}
+
+// as2variant returns the variant (V_*) flags of instruction as.
+int
+as2variant(int as)
+{
+       int i;
+       initvariants();
+       for(i=0; i<nelem(varianttable[as]); i++)
+               if(varianttable[as][i] == as)
+                       return i;
+       fatal("as2variant: instruction %A is not a variant of itself", as);
+       return 0;
+}
+
+// variant2as returns the instruction as with the given variant (V_*) flags.
+// If no such variant exists, this returns 0.
+int
+variant2as(int as, int flags)
+{
+       initvariants();
+       return varianttable[as][flags];
+}