summaryrefslogtreecommitdiff
path: root/gcc/gensupport.c
diff options
context:
space:
mode:
authorZack Weinberg <zack@gcc.gnu.org>2002-07-29 18:02:47 +0000
committerZack Weinberg <zack@gcc.gnu.org>2002-07-29 18:02:47 +0000
commit2199e5fade2d41cbdb19bb730e494613b9b7e262 (patch)
tree8880ef10951d3d1fbca761d1c3b95b762f0409e5 /gcc/gensupport.c
parent6ab185d6a53a5d77b86144d26414b5167778384a (diff)
downloadgcc-2199e5fade2d41cbdb19bb730e494613b9b7e262.tar.gz
gensupport.c: Include hashtab.h.
* gensupport.c: Include hashtab.h. (insn_elision, condition_table, hash_c_test, cmp_c_test, maybe_eval_c_test): New routines and data structures to support insn elision. (init_md_reader): Read and initialize the condition_table. (read_md_rtx): Discard insn patterns whose C test is provably always false. * gensupport.h: Declare new functions and data structures. * genconditions.c, dummy-conditions.c: New files. * Makefile.in: Build genconditions; run it to construct insn-conditions.c; build that and link it into most gen* programs. (HOST_SUPPORT, HOST_EARLY_SUPPORT): New variables. (GEN): Delete, unused. (STAGESTUFF): Update. * gencodes.c: (gen_insn): #define CODE_FOR_xxx equal to CODE_FOR_nothing for all elided patterns. (main): Tweaked to support this. * genflags.c (gen_proto): Emit a static inline generator function here for all elided patterns, which simply returns NULL_RTX. (gen_insn): Do not define HAVE_xxx for elided patterns. (main): Tweaked to support this. No need to forward-declare struct rtx_def. * genrecog.c: Do not bother emitting the C test if it's known to be true at compile time. From-SVN: r55839
Diffstat (limited to 'gcc/gensupport.c')
-rw-r--r--gcc/gensupport.c100
1 files changed, 99 insertions, 1 deletions
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index 9e3d0bbcb1f..5a9ff21f978 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -23,12 +23,15 @@
#include "rtl.h"
#include "obstack.h"
#include "errors.h"
+#include "hashtab.h"
#include "gensupport.h"
/* In case some macros used by files we include need it, define this here. */
int target_flags;
+int insn_elision = 1;
+
static struct obstack obstack;
struct obstack *rtl_obstack = &obstack;
@@ -39,6 +42,8 @@ static int predicable_default;
static const char *predicable_true;
static const char *predicable_false;
+static htab_t condition_table;
+
static char *base_dir = NULL;
/* We initially queue all patterns, process the define_insn and
@@ -950,6 +955,7 @@ init_md_reader (filename)
{
FILE *input_file;
int c;
+ size_t i;
char *lastsl;
lastsl = strrchr (filename, '/');
@@ -964,6 +970,14 @@ init_md_reader (filename)
return FATAL_EXIT_CODE;
}
+ /* Initialize the table of insn conditions. */
+ condition_table = htab_create (n_insn_conditions,
+ hash_c_test, cmp_c_test, NULL);
+
+ for (i = 0; i < n_insn_conditions; i++)
+ *(htab_find_slot (condition_table, (PTR) &insn_conditions[i], INSERT))
+ = (PTR) &insn_conditions[i];
+
obstack_init (rtl_obstack);
errors = 0;
sequence_num = 0;
@@ -1002,6 +1016,8 @@ read_md_rtx (lineno, seqnr)
struct queue_elem **queue, *elem;
rtx desc;
+ discard:
+
/* Read all patterns from a given queue before moving on to the next. */
if (define_attr_queue != NULL)
queue = &define_attr_queue;
@@ -1021,14 +1037,29 @@ read_md_rtx (lineno, seqnr)
free (elem);
+ /* Discard insn patterns which we know can never match (because
+ their C test is provably always false). If insn_elision is
+ false, our caller needs to see all the patterns. Note that the
+ elided patterns are never counted by the sequence numbering; it
+ it is the caller's responsibility, when insn_elision is false, not
+ to use elided pattern numbers for anything. */
switch (GET_CODE (desc))
{
case DEFINE_INSN:
case DEFINE_EXPAND:
+ if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
+ sequence_num++;
+ else if (insn_elision)
+ goto discard;
+ break;
+
case DEFINE_SPLIT:
case DEFINE_PEEPHOLE:
case DEFINE_PEEPHOLE2:
- sequence_num++;
+ if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
+ sequence_num++;
+ else if (insn_elision)
+ goto discard;
break;
default:
@@ -1038,6 +1069,73 @@ read_md_rtx (lineno, seqnr)
return desc;
}
+/* Helper functions for insn elision. */
+
+/* Compute a hash function of a c_test structure, which is keyed
+ by its ->expr field. */
+hashval_t
+hash_c_test (x)
+ const PTR x;
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const unsigned char *base, *s = (const unsigned char *) a->expr;
+ hashval_t hash;
+ unsigned char c;
+ unsigned int len;
+
+ base = s;
+ hash = 0;
+
+ while ((c = *s++) != '\0')
+ {
+ hash += c + (c << 17);
+ hash ^= hash >> 2;
+ }
+
+ len = s - base;
+ hash += len + (len << 17);
+ hash ^= hash >> 2;
+
+ return hash;
+}
+
+/* Compare two c_test expression structures. */
+int
+cmp_c_test (x, y)
+ const PTR x;
+ const PTR y;
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const struct c_test *b = (const struct c_test *) y;
+
+ return !strcmp (a->expr, b->expr);
+}
+
+/* Given a string representing a C test expression, look it up in the
+ condition_table and report whether or not its value is known
+ at compile time. Returns a tristate: 1 for known true, 0 for
+ known false, -1 for unknown. */
+int
+maybe_eval_c_test (expr)
+ const char *expr;
+{
+ const struct c_test *test;
+ struct c_test dummy;
+
+ if (expr[0] == 0)
+ return 1;
+
+ if (insn_elision_unavailable)
+ return -1;
+
+ dummy.expr = expr;
+ test = (const struct c_test *) htab_find (condition_table, &dummy);
+ if (!test)
+ abort ();
+
+ return test->value;
+}
+
/* Given a string, return the number of comma-separated elements in it.
Return 0 for the null string. */
int