diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-06-21 16:28:32 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-06-21 16:28:32 +0000 |
commit | a7534a68f03df3aad6e34ee5689d82797fe7d32f (patch) | |
tree | 29f14e53c48d6489b20c741647254ece6ecda2ea /gcc/genattrtab.c | |
parent | fdc86f975f675d897a1c6b0ff54ea9e875334bfb (diff) | |
download | gcc-a7534a68f03df3aad6e34ee5689d82797fe7d32f.tar.gz |
* Makefile.in (build/genattrtab.o): Depend on vecprim.h.
* genattrtab.c: Include vecprim.h.
(cached_attrs, cached_attr_count, attrs_seen_once,
attrs_seen_more_than_once, attrs_to_cache, attrs_cached_inside,
attrs_cached_after): New variables.
(find_attrs_to_cache): New function.
(FLG_BITWISE, FLG_AFTER, FLG_INSIDE, FLG_OUTSIDE_AND): Define.
(write_test_expr): Add attrs_cached argument, return it too,
attempt to cache non-const attributes used more than once in
a single case handling.
(write_attr_get): Use find_attrs_to_cache, for caching candidates
emit cached_* variables. Adjust write_attr_set callers.
(write_attr_set): Add attrs_cached attribute, use find_attrs_to_cache
to find attributes that should be cached in this block. Adjust
write_test_expr callers.
(write_attr_case): Clear attrs_to_cache. Adjust write_attr_set
callers.
(make_automaton_attrs): Adjust write_test_expr caller.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@161094 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/genattrtab.c')
-rw-r--r-- | gcc/genattrtab.c | 273 |
1 files changed, 237 insertions, 36 deletions
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index 33b66f34009..a86332d49e3 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -113,6 +113,7 @@ along with GCC; see the file COPYING3. If not see #include "errors.h" #include "read-md.h" #include "gensupport.h" +#include "vecprim.h" /* Flags for make_internal_attr's `special' parameter. */ #define ATTR_NONE 0 @@ -277,7 +278,7 @@ static void write_attr_valueq (struct attr_desc *, const char *); static struct attr_value *find_most_used (struct attr_desc *); static void write_attr_set (struct attr_desc *, int, rtx, const char *, const char *, rtx, - int, int); + int, int, unsigned int); static void write_attr_case (struct attr_desc *, struct attr_value *, int, const char *, const char *, int, rtx); static void write_attr_value (struct attr_desc *, rtx); @@ -3126,16 +3127,98 @@ gen_delay (rtx def, int lineno) delays = delay; } -/* Given a piece of RTX, print a C expression to test its truth value. - We use AND and IOR both for logical and bit-wise operations, so - interpret them as logical unless they are inside a comparison expression. - The first bit of FLAGS will be nonzero in that case. +/* Names of attributes that could be possibly cached. */ +static const char *cached_attrs[32]; +/* Number of such attributes. */ +static int cached_attr_count; +/* Bitmasks of possibly cached attributes. */ +static unsigned int attrs_seen_once, attrs_seen_more_than_once; +static unsigned int attrs_to_cache; +static unsigned int attrs_cached_inside, attrs_cached_after; - Set the second bit of FLAGS to make references to attribute values use - a cached local variable instead of calling a function. */ +/* Finds non-const attributes that could be possibly cached. + When create is TRUE, fills in cached_attrs array. + Computes ATTRS_SEEN_ONCE and ATTRS_SEEN_MORE_THAN_ONCE + bitmasks. */ static void -write_test_expr (rtx exp, int flags) +find_attrs_to_cache (rtx exp, bool create) +{ + int i; + const char *name; + struct attr_desc *attr; + + if (exp == NULL) + return; + + switch (GET_CODE (exp)) + { + case NOT: + if (GET_CODE (XEXP (exp, 0)) == EQ_ATTR) + find_attrs_to_cache (XEXP (exp, 0), create); + return; + + case EQ_ATTR: + name = XSTR (exp, 0); + if (name == alternative_name) + return; + for (i = 0; i < cached_attr_count; i++) + if (name == cached_attrs[i]) + { + if ((attrs_seen_once & (1U << i)) != 0) + attrs_seen_more_than_once |= (1U << i); + else + attrs_seen_once |= (1U << i); + return; + } + if (!create) + return; + attr = find_attr (&name, 0); + gcc_assert (attr); + if (attr->is_const) + return; + if (cached_attr_count == 32) + return; + cached_attrs[cached_attr_count] = XSTR (exp, 0); + attrs_seen_once |= (1U << cached_attr_count); + cached_attr_count++; + return; + + case AND: + case IOR: + find_attrs_to_cache (XEXP (exp, 0), create); + find_attrs_to_cache (XEXP (exp, 1), create); + return; + + case COND: + for (i = 0; i < XVECLEN (exp, 0); i += 2) + find_attrs_to_cache (XVECEXP (exp, 0, i), create); + return; + + default: + return; + } +} + +/* Given a piece of RTX, print a C expression to test its truth value. + We use AND and IOR both for logical and bit-wise operations, so + interpret them as logical unless they are inside a comparison expression. */ + +/* Interpret AND/IOR as bit-wise operations instead of logical. */ +#define FLG_BITWISE 1 +/* Set if cached attribute will be known initialized in else block after + this condition. This is true for LHS of toplevel && and || and + even for RHS of ||, but not for RHS of &&. */ +#define FLG_AFTER 2 +/* Set if cached attribute will be known initialized in then block after + this condition. This is true for LHS of toplevel && and || and + even for RHS of &&, but not for RHS of ||. */ +#define FLG_INSIDE 4 +/* Cleared when an operand of &&. */ +#define FLG_OUTSIDE_AND 8 + +static unsigned int +write_test_expr (rtx exp, unsigned int attrs_cached, int flags) { int comparison_operator = 0; RTX_CODE code; @@ -3157,12 +3240,30 @@ write_test_expr (rtx exp, int flags) case EQ: case NE: case GE: case GT: case LE: case LT: - comparison_operator = 1; + comparison_operator = FLG_BITWISE; case PLUS: case MINUS: case MULT: case DIV: case MOD: case AND: case IOR: case XOR: case ASHIFT: case LSHIFTRT: case ASHIFTRT: - write_test_expr (XEXP (exp, 0), flags | comparison_operator); + if ((code != AND && code != IOR) || (flags & FLG_BITWISE)) + { + flags &= ~(FLG_AFTER | FLG_INSIDE | FLG_OUTSIDE_AND); + write_test_expr (XEXP (exp, 0), attrs_cached, + flags | comparison_operator); + } + else + { + if (code == AND) + flags &= ~FLG_OUTSIDE_AND; + if (GET_CODE (XEXP (exp, 0)) == code + || GET_CODE (XEXP (exp, 0)) == EQ_ATTR + || (GET_CODE (XEXP (exp, 0)) == NOT + && GET_CODE (XEXP (XEXP (exp, 0), 0)) == EQ_ATTR)) + attrs_cached + = write_test_expr (XEXP (exp, 0), attrs_cached, flags); + else + write_test_expr (XEXP (exp, 0), attrs_cached, flags); + } switch (code) { case EQ: @@ -3211,13 +3312,13 @@ write_test_expr (rtx exp, int flags) printf (" %% "); break; case AND: - if (flags & 1) + if (flags & FLG_BITWISE) printf (" & "); else printf (" && "); break; case IOR: - if (flags & 1) + if (flags & FLG_BITWISE) printf (" | "); else printf (" || "); @@ -3236,15 +3337,49 @@ write_test_expr (rtx exp, int flags) gcc_unreachable (); } - write_test_expr (XEXP (exp, 1), flags | comparison_operator); + if (code == AND) + { + /* For if (something && (cached_x = get_attr_x (insn)) == X) + cached_x is only known to be initialized in then block. */ + flags &= ~FLG_AFTER; + } + else if (code == IOR) + { + if (flags & FLG_OUTSIDE_AND) + /* For if (something || (cached_x = get_attr_x (insn)) == X) + cached_x is only known to be initialized in else block + and else if conditions. */ + flags &= ~FLG_INSIDE; + else + /* For if ((something || (cached_x = get_attr_x (insn)) == X) + && something_else) + cached_x is not know to be initialized anywhere. */ + flags &= ~(FLG_AFTER | FLG_INSIDE); + } + if ((code == AND || code == IOR) + && (GET_CODE (XEXP (exp, 1)) == code + || GET_CODE (XEXP (exp, 1)) == EQ_ATTR + || (GET_CODE (XEXP (exp, 1)) == NOT + && GET_CODE (XEXP (XEXP (exp, 1), 0)) == EQ_ATTR))) + attrs_cached + = write_test_expr (XEXP (exp, 1), attrs_cached, flags); + else + write_test_expr (XEXP (exp, 1), attrs_cached, + flags | comparison_operator); break; case NOT: /* Special-case (not (eq_attrq "alternative" "x")) */ - if (! (flags & 1) && GET_CODE (XEXP (exp, 0)) == EQ_ATTR - && XSTR (XEXP (exp, 0), 0) == alternative_name) + if (! (flags & FLG_BITWISE) && GET_CODE (XEXP (exp, 0)) == EQ_ATTR) { - printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1)); + if (XSTR (XEXP (exp, 0), 0) == alternative_name) + { + printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1)); + break; + } + + printf ("! "); + attrs_cached = write_test_expr (XEXP (exp, 0), attrs_cached, flags); break; } @@ -3255,7 +3390,7 @@ write_test_expr (rtx exp, int flags) switch (code) { case NOT: - if (flags & 1) + if (flags & FLG_BITWISE) printf ("~ "); else printf ("! "); @@ -3270,14 +3405,15 @@ write_test_expr (rtx exp, int flags) gcc_unreachable (); } - write_test_expr (XEXP (exp, 0), flags); + flags &= ~(FLG_AFTER | FLG_INSIDE | FLG_OUTSIDE_AND); + write_test_expr (XEXP (exp, 0), attrs_cached, flags); break; case EQ_ATTR_ALT: { int set = XINT (exp, 0), bit = 0; - if (flags & 1) + if (flags & FLG_BITWISE) fatal ("EQ_ATTR_ALT not valid inside comparison"); if (!set) @@ -3323,7 +3459,7 @@ write_test_expr (rtx exp, int flags) have been removed by optimization. Handle "alternative" specially and give error if EQ_ATTR present inside a comparison. */ case EQ_ATTR: - if (flags & 1) + if (flags & FLG_BITWISE) fatal ("EQ_ATTR not valid inside comparison"); if (XSTR (exp, 0) == alternative_name) @@ -3340,12 +3476,26 @@ write_test_expr (rtx exp, int flags) { write_test_expr (evaluate_eq_attr (exp, attr, attr->default_val->value, -2, -2), - flags); + attrs_cached, 0); } else { - if (flags & 2) - printf ("attr_%s", attr->name); + int i; + for (i = 0; i < cached_attr_count; i++) + if (attr->name == cached_attrs[i]) + break; + if (i < cached_attr_count && (attrs_cached & (1U << i)) != 0) + printf ("cached_%s", attr->name); + else if (i < cached_attr_count && (attrs_to_cache & (1U << i)) != 0) + { + printf ("(cached_%s = get_attr_%s (insn))", + attr->name, attr->name); + if (flags & FLG_AFTER) + attrs_cached_after |= (1U << i); + if (flags & FLG_INSIDE) + attrs_cached_inside |= (1U << i); + attrs_cached |= (1U << i); + } else printf ("get_attr_%s (insn)", attr->name); printf (" == "); @@ -3355,7 +3505,7 @@ write_test_expr (rtx exp, int flags) /* Comparison test of flags for define_delays. */ case ATTR_FLAG: - if (flags & 1) + if (flags & FLG_BITWISE) fatal ("ATTR_FLAG not valid inside comparison"); printf ("(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0)); break; @@ -3407,11 +3557,11 @@ write_test_expr (rtx exp, int flags) break; case IF_THEN_ELSE: - write_test_expr (XEXP (exp, 0), flags & 2); + write_test_expr (XEXP (exp, 0), attrs_cached, 0); printf (" ? "); - write_test_expr (XEXP (exp, 1), flags | 1); + write_test_expr (XEXP (exp, 1), attrs_cached, FLG_BITWISE); printf (" : "); - write_test_expr (XEXP (exp, 2), flags | 1); + write_test_expr (XEXP (exp, 2), attrs_cached, FLG_BITWISE); break; default: @@ -3420,6 +3570,7 @@ write_test_expr (rtx exp, int flags) } printf (")"); + return attrs_cached; } /* Given an attribute value, return the maximum CONST_STRING argument @@ -3624,6 +3775,7 @@ static void write_attr_get (struct attr_desc *attr) { struct attr_value *av, *common_av; + int i, j; /* Find the most used attribute value. Handle that as the `default' of the switch we will generate. */ @@ -3653,16 +3805,48 @@ write_attr_get (struct attr_desc *attr) if (av->num_insns == 1) write_attr_set (attr, 2, av->value, "return", ";", true_rtx, av->first_insn->def->insn_code, - av->first_insn->def->insn_index); + av->first_insn->def->insn_index, 0); else if (av->num_insns != 0) write_attr_set (attr, 2, av->value, "return", ";", - true_rtx, -2, 0); + true_rtx, -2, 0, 0); printf ("}\n\n"); return; } printf ("{\n"); + + /* Find attributes that are worth caching in the conditions. */ + cached_attr_count = 0; + attrs_seen_more_than_once = 0; + for (av = attr->first_value; av; av = av->next) + { + attrs_seen_once = 0; + find_attrs_to_cache (av->value, true); + } + /* Remove those that aren't worth caching from the array. */ + for (i = 0, j = 0; i < cached_attr_count; i++) + if ((attrs_seen_more_than_once & (1U << i)) != 0) + { + const char *name = cached_attrs[i]; + struct attr_desc *cached_attr; + if (i != j) + cached_attrs[j] = name; + cached_attr = find_attr (&name, 0); + gcc_assert (cached_attr && cached_attr->is_const == 0); + if (cached_attr->enum_name) + printf (" enum %s", cached_attr->enum_name); + else if (!cached_attr->is_numeric) + printf (" enum attr_%s", cached_attr->name); + else + printf (" int"); + printf (" cached_%s ATTRIBUTE_UNUSED;\n", name); + j++; + } + cached_attr_count = j; + if (cached_attr_count) + printf ("\n"); + printf (" switch (recog_memoized (insn))\n"); printf (" {\n"); @@ -3672,6 +3856,7 @@ write_attr_get (struct attr_desc *attr) write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx); printf (" }\n}\n\n"); + cached_attr_count = 0; } /* Given an AND tree of known true terms (because we are inside an `if' with @@ -3710,7 +3895,7 @@ eliminate_known_true (rtx known_true, rtx exp, int insn_code, int insn_index) static void write_attr_set (struct attr_desc *attr, int indent, rtx value, const char *prefix, const char *suffix, rtx known_true, - int insn_code, int insn_index) + int insn_code, int insn_index, unsigned int attrs_cached) { if (GET_CODE (value) == COND) { @@ -3722,6 +3907,15 @@ write_attr_set (struct attr_desc *attr, int indent, rtx value, int first_if = 1; int i; + if (cached_attr_count) + { + attrs_seen_once = 0; + attrs_seen_more_than_once = 0; + for (i = 0; i < XVECLEN (value, 0); i += 2) + find_attrs_to_cache (XVECEXP (value, 0, i), false); + attrs_to_cache |= attrs_seen_more_than_once; + } + for (i = 0; i < XVECLEN (value, 0); i += 2) { rtx testexp; @@ -3752,17 +3946,22 @@ write_attr_set (struct attr_desc *attr, int indent, rtx value, if (inner_true == false_rtx) continue; + attrs_cached_inside = attrs_cached; + attrs_cached_after = attrs_cached; write_indent (indent); printf ("%sif ", first_if ? "" : "else "); first_if = 0; - write_test_expr (testexp, 0); + write_test_expr (testexp, attrs_cached, + (FLG_AFTER | FLG_INSIDE | FLG_OUTSIDE_AND)); + attrs_cached = attrs_cached_after; printf ("\n"); write_indent (indent + 2); printf ("{\n"); write_attr_set (attr, indent + 4, XVECEXP (value, 0, i + 1), prefix, suffix, - inner_true, insn_code, insn_index); + inner_true, insn_code, insn_index, + attrs_cached_inside); write_indent (indent + 2); printf ("}\n"); our_known_true = newexp; @@ -3777,7 +3976,8 @@ write_attr_set (struct attr_desc *attr, int indent, rtx value, } write_attr_set (attr, first_if ? indent : indent + 4, default_val, - prefix, suffix, our_known_true, insn_code, insn_index); + prefix, suffix, our_known_true, insn_code, insn_index, + attrs_cached); if (! first_if) { @@ -3858,13 +4058,14 @@ write_attr_case (struct attr_desc *attr, struct attr_value *av, printf ("extract_insn_cached (insn);\n"); } + attrs_to_cache = 0; if (av->num_insns == 1) write_attr_set (attr, indent + 2, av->value, prefix, suffix, known_true, av->first_insn->def->insn_code, - av->first_insn->def->insn_index); + av->first_insn->def->insn_index, 0); else write_attr_set (attr, indent + 2, av->value, prefix, suffix, - known_true, -2, 0); + known_true, -2, 0, 0); if (strncmp (prefix, "return", 6)) { @@ -4547,7 +4748,7 @@ make_automaton_attrs (void) } else printf (" else if ("); - write_test_expr (test, 0); + write_test_expr (test, 0, 0); printf (")\n"); printf (" {\n"); printf (" internal_dfa_insn_code\n"); |