aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2006-06-28 19:42:04 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2006-06-28 19:42:04 +0000
commit7caf673482793e0174935b61b40f9ba9c1554b8d (patch)
tree1b7a5428f281a483e6b154d91478e0ba051645df
parent092b194ebfc458d451ca2e930e6a06146fcf52b1 (diff)
downloadgcc-7caf673482793e0174935b61b40f9ba9c1554b8d.zip
gcc-7caf673482793e0174935b61b40f9ba9c1554b8d.tar.gz
gcc-7caf673482793e0174935b61b40f9ba9c1554b8d.tar.bz2
genpreds.c (generate_switch_p): New function.
* genpreds.c (generate_switch_p): New function. (add_mode_tests): Push the new mode test down inside an AND expr if this allows the switch-suitable MATCH_CODE to be near the root. (write_match_code_switch): New function to write a MATCH_CODE as a switch statement. (write_predicate_stmts): New function to write a predicate RTX expression as a sequence of statements. (write_one_predicate_function): Use write_predicate_stmts. (write_tm_constrs_h): Likewise. From-SVN: r115055
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/genpreds.c124
2 files changed, 128 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6ff1846..32d28ba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2006-06-28 Roger Sayle <roger@eyesopen.com>
+
+ * genpreds.c (generate_switch_p): New function.
+ (add_mode_tests): Push the new mode test down inside an AND expr
+ if this allows the switch-suitable MATCH_CODE to be near the root.
+ (write_match_code_switch): New function to write a MATCH_CODE as
+ a switch statement.
+ (write_predicate_stmts): New function to write a predicate RTX
+ expression as a sequence of statements.
+ (write_one_predicate_function): Use write_predicate_stmts.
+ (write_tm_constrs_h): Likewise.
+
2006-06-26 Fred Fish <fnf@specifix.com>
* config/mips/t-sb1: New file.
diff --git a/gcc/genpreds.c b/gcc/genpreds.c
index 7c732bb..41efc54 100644
--- a/gcc/genpreds.c
+++ b/gcc/genpreds.c
@@ -316,6 +316,15 @@ mark_mode_tests (rtx exp)
}
}
+/* Determine whether the expression EXP is a MATCH_CODE that should
+ be written as a switch statement. */
+static bool
+generate_switch_p (rtx exp)
+{
+ return GET_CODE (exp) == MATCH_CODE
+ && strchr (XSTR (exp, 0), ',');
+}
+
/* Given a predicate, work out where in its RTL expression to add
tests for proper modes. Special predicates do not get any such
tests. We try to avoid adding tests when we don't have to; in
@@ -361,6 +370,15 @@ add_mode_tests (struct pred_data *p)
switch (GET_CODE (subexp))
{
+ case AND:
+ /* The switch code generation in write_predicate_stmts prefers
+ rtx code tests to be at the top of the expression tree. So
+ push this AND down into the second operand of an exisiting
+ AND expression. */
+ if (generate_switch_p (XEXP (subexp, 0)))
+ pos = &XEXP (subexp, 1);
+ goto break_loop;
+
case IOR:
{
int test0 = NO_MODE_TEST (XEXP (subexp, 0));
@@ -520,6 +538,98 @@ write_predicate_expr (rtx exp)
}
}
+/* Write the MATCH_CODE expression EXP as a switch statement. */
+
+static void
+write_match_code_switch (rtx exp)
+{
+ const char *codes = (const char *) XEXP (exp, 0);
+ const char *path = (const char *) XEXP (exp, 1);
+ const char *code;
+
+ fputs (" switch (GET_CODE (", stdout);
+ write_extract_subexp (path);
+ fputs ("))\n {\n", stdout);
+
+ while ((code = scan_comma_elt (&codes)) != 0)
+ {
+ fputs (" case ", stdout);
+ while (code < codes)
+ {
+ putchar (TOUPPER (*code));
+ code++;
+ }
+ fputs(":\n", stdout);
+ }
+}
+
+/* Given a predictate expression EXP, write out a sequence of stmts
+ to evaluate it. This is similar to write_predicate_expr but can
+ generate efficient switch statements. */
+
+static void
+write_predicate_stmts (rtx exp)
+{
+ switch (GET_CODE (exp))
+ {
+ case MATCH_CODE:
+ if (generate_switch_p (exp))
+ {
+ write_match_code_switch (exp);
+ puts (" return true;\n"
+ " default:\n"
+ " break;\n"
+ " }\n"
+ " return false;");
+ return;
+ }
+ break;
+
+ case AND:
+ if (generate_switch_p (XEXP (exp, 0)))
+ {
+ write_match_code_switch (XEXP (exp, 0));
+ puts (" break;\n"
+ " default:\n"
+ " return false;\n"
+ " }");
+ exp = XEXP (exp, 1);
+ }
+ break;
+
+ case IOR:
+ if (generate_switch_p (XEXP (exp, 0)))
+ {
+ write_match_code_switch (XEXP (exp, 0));
+ puts (" return true;\n"
+ " default:\n"
+ " break;\n"
+ " }");
+ exp = XEXP (exp, 1);
+ }
+
+ case NOT:
+ if (generate_switch_p (XEXP (exp, 0)))
+ {
+ write_match_code_switch (XEXP (exp, 0));
+ puts (" return false;\n"
+ " default:\n"
+ " break;\n"
+ " }\n"
+ " return true;");
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ fputs(" return ",stdout);
+ write_predicate_expr (exp);
+ fputs(";\n", stdout);
+}
+
/* Given a predicate, write out a complete C function to compute it. */
static void
write_one_predicate_function (struct pred_data *p)
@@ -532,11 +642,10 @@ write_one_predicate_function (struct pred_data *p)
/* A normal predicate can legitimately not look at enum machine_mode
if it accepts only CONST_INTs and/or CONST_DOUBLEs. */
- printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n"
- "{\n return ",
+ printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n{\n",
p->name);
- write_predicate_expr (p->exp);
- fputs (";\n}\n\n", stdout);
+ write_predicate_stmts (p->exp);
+ fputs ("}\n\n", stdout);
}
/* Constraints fall into two categories: register constraints
@@ -995,10 +1104,9 @@ write_tm_constrs_h (void)
if (needs_rval)
puts (" if (GET_CODE (op) == CONST_DOUBLE && mode != VOIDmode)"
" rval = CONST_DOUBLE_REAL_VALUE (op);");
-
- fputs (" return ", stdout);
- write_predicate_expr (c->exp);
- fputs (";\n}\n", stdout);
+
+ write_predicate_stmts (c->exp);
+ fputs ("}\n", stdout);
}
puts ("#endif /* tm-constrs.h */");
}