This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

make genattrtab generate smaller code


Hi,

this patch makes the code in insn-attrtab.c cache the attributes.
It currently generates code like:

enum attr_x get_attr_lala (rtx insn) {
switch (recog_memoized(insn)) {
case xxx:
  if (bla && get_attr_memory(insn) == XXX) {
  } else if (blubb && get_attr_memory(insn) == XXX) {
  } else if (bla2 && get_attr_memory(insn) == YYY) {
  } else {
  }
default:
} }

This patch moves all the get_attr_xxx calls inside the if()s to the front
of the function by caching the results, in order to save several
hundred function calls, i.e. like:

enum attr_x get_attr_lala (rtx insn) {
enum attr_memory attr_memory = get_attr_memory(insn);
switch (recog_memoized(insn)) {
case xxx:
  if (bla && attr_memory == XXX) {
  } else if (blubb && attr_memory == XXX) {
  } else if (bla2 && attr_memory == YYY) {
  } else {
  }
default:
} }

A result of this is (on x86):
 matz     suse      1601778 2003-09-05 14:07 insn-attrtab.old.c
 matz     suse       793008 2003-09-05 15:01 insn-attrtab.old.o
 matz     suse      1550943 2003-09-05 20:56 insn-attrtab.c
 matz     suse       699704 2003-09-05 20:56 insn-attrtab.o

% size insn-attrtab.o insn-attrtab.old.o
   text    data     bss     dec     hex filename
 325144       8     892  326044   4f99c insn-attrtab.o
 374060       8     892  374960   5b8b0 insn-attrtab.old.o

Bootstraptimes don't change much.  Time for booting C,C++ (-j4)
HEAD
  real    13m39.093s
  user    39m22.830s
  sys     2m17.970s
HEAD+patch
  real    13m16.332s
  user    38m56.860s
  sys     2m20.070s

Bootstrapped (all langs - treelang), no regressions, i686-linux.

I also experimented with merging the multiple test on which_alternative to
use '&', ala
  if ((which_alternative == 1) || (which_alternative == 2))
-->
  if ((1 << which_alternative) & 0x6)

but this didn't result in smaller or faster code.  Maybe I should do this
only if at least three bits are set in the mask (instead of two in my
experiments).


Ciao,
Michael.

2003-09-05  Michael Matz  <matz@suse.de>

        * genattrtab.c (write_cache_used_attributes): New.
        (write_attr_get, write_eligible_delay,
        write_complex_function): Use it.
        (write_attr_set): Calling write_test_expr() with caching flag.

Index: genattrtab.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genattrtab.c,v
retrieving revision 1.136
diff -u -p -r1.136 genattrtab.c
--- genattrtab.c	22 Aug 2003 06:45:14 -0000	1.136
+++ genattrtab.c	5 Sep 2003 18:54:38 -0000
@@ -435,6 +435,7 @@ static rtx eliminate_known_true (rtx, rt
 static void write_attr_set	(struct attr_desc *, int, rtx,
 				 const char *, const char *, rtx,
 				 int, int);
+static void write_cache_used_attributes (struct attr_desc *);
 static void write_attr_case	(struct attr_desc *, struct attr_value *,
 				 int, const char *, const char *, int, rtx);
 static void write_unit_name	(const char *, int, const char *);
@@ -4749,6 +4750,23 @@ walk_attr_value (rtx exp)
       }
 }

+static void
+write_cache_used_attributes (struct attr_desc *attr)
+{
+  struct attr_value *av;
+  struct attr_desc *attr2;
+  int i;
+
+  printf ("{ ");
+  for (i = 0; i < MAX_ATTRS_INDEX; ++i)
+    for (attr2 = attrs[i]; attr2; attr2 = attr2->next)
+      if (!attr2->is_const)
+        for (av = attr->first_value; av; av = av->next)
+          if (av->num_insns != 0)
+            if (write_expr_attr_cache (av->value, attr2))
+              break;
+}
+
 /* Write out a function to obtain the attribute for a given INSN.  */

 static void
@@ -4782,13 +4800,14 @@ write_attr_get (struct attr_desc *attr)
       printf ("get_attr_%s (void)\n", attr->name);
       printf ("{\n");

+      write_cache_used_attributes (attr);
       for (av = attr->first_value; av; av = av->next)
 	if (av->num_insns != 0)
 	  write_attr_set (attr, 2, av->value, "return", ";",
 			  true_rtx, av->first_insn->insn_code,
 			  av->first_insn->insn_index);

-      printf ("}\n\n");
+      printf ("}}\n\n");
       return;
     }

@@ -4814,6 +4833,7 @@ write_attr_get (struct attr_desc *attr)
     }
   else
     {
+      write_cache_used_attributes (attr);
       printf ("  switch (recog_memoized (insn))\n");
       printf ("    {\n");

@@ -4822,7 +4842,7 @@ write_attr_get (struct attr_desc *attr)
 	  write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);

       write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
-      printf ("    }\n}\n\n");
+      printf ("    }}\n}\n\n");
     }
 }

@@ -4907,7 +4927,7 @@ write_attr_set (struct attr_desc *attr,
 	  write_indent (indent);
 	  printf ("%sif ", first_if ? "" : "else ");
 	  first_if = 0;
-	  write_test_expr (testexp, 0);
+	  write_test_expr (testexp, 2);
 	  printf ("\n");
 	  write_indent (indent + 2);
 	  printf ("{\n");
@@ -5284,6 +5304,7 @@ write_eligible_delay (const char *kind)
       common_av = find_most_used (attr);

       printf ("  insn = delay_insn;\n");
+      write_cache_used_attributes (attr);
       printf ("  switch (recog_memoized (insn))\n");
       printf ("    {\n");

@@ -5293,7 +5314,7 @@ write_eligible_delay (const char *kind)
 	  write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx);

       write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx);
-      printf ("    }\n\n");
+      printf ("    }}\n\n");

       /* Ensure matched.  Otherwise, shouldn't have been called.  */
       printf ("  if (slot < %d)\n", max_slots);
@@ -5303,21 +5324,22 @@ write_eligible_delay (const char *kind)
   /* If just one type of delay slot, write simple switch.  */
   if (num_delays == 1 && max_slots == 1)
     {
-      printf ("  insn = candidate_insn;\n");
-      printf ("  switch (recog_memoized (insn))\n");
-      printf ("    {\n");
-
       attr = find_attr ("*delay_1_0", 0);
       if (! attr)
 	abort ();
       common_av = find_most_used (attr);

+      printf ("  insn = candidate_insn;\n");
+      write_cache_used_attributes (attr);
+      printf ("  switch (recog_memoized (insn))\n");
+      printf ("    {\n");
+
       for (av = attr->first_value; av; av = av->next)
 	if (av != common_av)
 	  write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);

       write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
-      printf ("    }\n");
+      printf ("    }}\n");
     }

   else
@@ -5331,23 +5353,24 @@ write_eligible_delay (const char *kind)
       for (delay = delays; delay; delay = delay->next)
 	for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
 	  {
-	    printf ("    case %d:\n",
-		    (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
-	    printf ("      switch (recog_memoized (insn))\n");
-	    printf ("\t{\n");
-
 	    sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
 	    attr = find_attr (str, 0);
 	    if (! attr)
 	      abort ();
 	    common_av = find_most_used (attr);

+	    printf ("    case %d:\n",
+		    (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
+	    write_cache_used_attributes (attr);
+	    printf ("      switch (recog_memoized (insn))\n");
+	    printf ("\t{\n");
+
 	    for (av = attr->first_value; av; av = av->next)
 	      if (av != common_av)
 		write_attr_case (attr, av, 1, "return", ";", 8, true_rtx);

 	    write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx);
-	    printf ("      }\n");
+	    printf ("      }}\n");
 	  }

       printf ("    default:\n");
@@ -5444,6 +5467,15 @@ write_complex_function (struct function_
   int using_case;
   int i;

+  /* Write the `switch' statement to get the case value.  */
+  if (strlen (unit->name) + sizeof "*_cases" > 256)
+    abort ();
+  sprintf (str, "*%s_cases", unit->name);
+  case_attr = find_attr (str, 0);
+  if (! case_attr)
+    abort ();
+  common_av = find_most_used (case_attr);
+
   printf ("static int\n");
   printf ("%s_unit_%s (rtx executing_insn, rtx candidate_insn)\n",
 	  unit->name, name);
@@ -5451,18 +5483,10 @@ write_complex_function (struct function_
   printf ("  rtx insn;\n");
   printf ("  int casenum;\n\n");
   printf ("  insn = executing_insn;\n");
+  write_cache_used_attributes (case_attr);
   printf ("  switch (recog_memoized (insn))\n");
   printf ("    {\n");

-  /* Write the `switch' statement to get the case value.  */
-  if (strlen (unit->name) + sizeof "*_cases" > 256)
-    abort ();
-  sprintf (str, "*%s_cases", unit->name);
-  case_attr = find_attr (str, 0);
-  if (! case_attr)
-    abort ();
-  common_av = find_most_used (case_attr);
-
   for (av = case_attr->first_value; av; av = av->next)
     if (av != common_av)
       write_attr_case (case_attr, av, 1,
@@ -5470,7 +5494,7 @@ write_complex_function (struct function_

   write_attr_case (case_attr, common_av, 0,
 		   "casenum =", ";", 4, unit->condexp);
-  printf ("    }\n\n");
+  printf ("    }}\n\n");

   /* Now write an outer switch statement on each case.  Then write
      the tests on the executing function within each.  */
@@ -5496,6 +5520,7 @@ write_complex_function (struct function_
       if (! attr)
 	abort ();

+      write_cache_used_attributes (attr);
       /* If single value, just write it.  */
       value = find_single_value (attr);
       if (value)
@@ -5515,6 +5540,7 @@ write_complex_function (struct function_
 			   "return", ";", 8, unit->condexp);
 	  printf ("      }\n\n");
 	}
+      printf ("}\n");
     }

   /* This default case should not be needed, but gcc's analysis is not


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]