From: "Rafael Espindola" <espindola@google.com>
To: "Richard Guenther" <rguenther@suse.de>
Cc: gcc-patches@gcc.gnu.org, "Diego Novillo" <dnovillo@google.com>
Subject: Re: [PATCH] Fix PR14495 (1/2)
Date: Wed, 16 Apr 2008 12:32:00 -0000 [thread overview]
Message-ID: <38a0d8450804160439k678281f7wc4f6ca74990ff3fd@mail.gmail.com> (raw)
In-Reply-To: <Pine.LNX.4.64.0804161016390.4180@zhemvz.fhfr.qr>
[-- Attachment #1: Type: text/plain, Size: 1424 bytes --]
> + size_t i, j;
> + bool min_take_default = !find_case_label_index (vec, 0, min, &i);
> + bool max_take_default = !find_case_label_index (vec, i, max, &j);
> +
>
> + if (i == j
> + && !min_take_default
> + && !max_take_default)
> + {
> + *min_idx = i;
> + *max_idx = j;
> + return true;
> + }
>
> + else if (i == j
> + && min_take_default
> + && max_take_default)
> + {
> + *min_idx = 1;
> + *max_idx = 0;
>
> ... this looks weird to me. Why not store i and j as well
> (and merge it with the previous case - IMHO both need a
> short comment, /* Exactly one case label reached. */
> and /* Only the default case label reached. */). Doesn't
> your rewrite guarantee that you can simply do
>
> /* If we reach exactly one case label. */
> if (i == j)
> {
> gcc_assert (min_take_default == max_take_default);
> *min_idx = i;
> *max_idx = j;
> return !min_take_default;
> }
>
> ?
We must return an empty range if we use only the default statement.
> Otherwise the patch looks fine.
I have updated the patch with your comments and some simplifications.
It is currently bootstrapping. OK if it has no regressions?
> Thanks,
> Richard.
Cheers,
--
Rafael Avila de Espindola
Google Ireland Ltd.
Gordon House
Barrow Street
Dublin 4
Ireland
Registered in Dublin, Ireland
Registration Number: 368047
[-- Attachment #2: vrp.patch --]
[-- Type: application/octet-stream, Size: 7454 bytes --]
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c (revision 134344)
+++ gcc/tree-vrp.c (working copy)
@@ -5528,59 +5528,120 @@
return (*taken_edge_p) ? SSA_PROP_INTERESTING : SSA_PROP_VARYING;
}
+/* Searches the case label vector VEC for the index *IDX of the CASE_LABEL
+ that includes the value VAL. The search is restricted to the range
+ [START_IDX, n - 2] where n is the size of VEC (n - 1 is the default label).
-/* Searches the case label vector VEC for the index *IDX the CASE_LABEL
- includes the value VAL. The search starts at index START_IDX and
- true is returned if *IDX corresponds to such an index. False is
- returned in case VAL hits the default case label and *IDX in this
- case is the next higher or the next lower case label index. */
+ If there is a CASE_LABEL for VAL, its index is placed in IDX and true is
+ returned.
+ If there is no CASE_LABEL for VAL and the is one that is larger than VAL,
+ it is placed in IDX and false is returned.
+
+ If VAL is larger than any CASE_LABEL, n - 1 is placed on IDX and false is
+ returned. */
+
static bool
find_case_label_index (tree vec, size_t start_idx, tree val, size_t *idx)
{
size_t n = TREE_VEC_LENGTH (vec);
- size_t low, high, i = start_idx;
+ size_t low, high;
- /* Find case label for minimum of the value range or the next one. */
- for (low = start_idx - 1, high = n - 1; high - low > 1; )
+ /* Find case label for minimum of the value range or the next one.
+ At each iteration we are searching in [low, high - 1]. */
+
+ for (low = start_idx, high = n - 1; high != low; )
{
tree t;
int cmp;
- i = (high + low) / 2;
+ /* Note that i != high, so we never ask for n - 1. */
+ size_t i = (high + low) / 2;
t = TREE_VEC_ELT (vec, i);
/* Cache the result of comparing CASE_LOW and val. */
cmp = tree_int_cst_compare (CASE_LOW (t), val);
- if (cmp > 0)
+ if (cmp == 0)
+ {
+ /* Ranges cannot be empty. */
+ *idx = i;
+ return true;
+ }
+ else if (cmp > 0)
high = i;
else
- low = i;
-
- if (CASE_HIGH (t) == NULL)
- {
- /* A singe-valued case label. */
- if (cmp == 0)
+ {
+ low = i + 1;
+ if (CASE_HIGH (t) != NULL
+ && tree_int_cst_compare (CASE_HIGH (t), val) >= 0)
{
*idx = i;
return true;
}
}
- else
- {
- /* A case range. We can only handle integer ranges. */
- if (cmp <= 0 && tree_int_cst_compare (CASE_HIGH (t), val) >= 0)
- {
- *idx = i;
- return true;
- }
- }
}
- *idx = i;
+ *idx = high;
return false;
}
+/* Searches the case label vector VEC for the range of CASE_LABELs that is used
+ for values between MIN and MAX. The first index is placed in MIN_IDX. The
+ last index is placed in MAX_IDX. If the range of CASE_LABELs is empty
+ then MAX_IDX < MIN_IDX.
+ Returns true if the default label is not needed. */
+
+static bool
+find_case_label_range (tree vec, tree min, tree max, size_t *min_idx, size_t *max_idx)
+{
+ size_t i, j;
+ bool min_take_default = !find_case_label_index (vec, 0, min, &i);
+ bool max_take_default = !find_case_label_index (vec, i, max, &j);
+
+ if (i == j
+ && min_take_default
+ && max_take_default)
+ {
+ /* Only the default case label reached.
+ Return an empty range. */
+ *min_idx = 1;
+ *max_idx = 0;
+ return false;
+ }
+ else
+ {
+ bool take_default = min_take_default || max_take_default;
+ tree low, high;
+ size_t k;
+
+ if (max_take_default)
+ j--;
+
+ /* If the case label range is continuous, we do not need
+ the default case label. Verify that. */
+ high = CASE_LOW (TREE_VEC_ELT (vec, i));
+ if (CASE_HIGH (TREE_VEC_ELT (vec, i)))
+ high = CASE_HIGH (TREE_VEC_ELT (vec, i));
+ for (k = i + 1; k <= j; ++k)
+ {
+ low = CASE_LOW (TREE_VEC_ELT (vec, k));
+ if (!integer_onep (int_const_binop (MINUS_EXPR, low, high, 0)))
+ {
+ take_default = true;
+ break;
+ }
+ high = low;
+ if (CASE_HIGH (TREE_VEC_ELT (vec, k)))
+ high = CASE_HIGH (TREE_VEC_ELT (vec, k));
+ }
+
+ *min_idx = i;
+ *max_idx = j;
+
+ return !take_default;
+ }
+}
+
/* Visit switch statement STMT. If we can determine which edge
will be taken out of STMT's basic block, record it in
*TAKEN_EDGE_P and return SSA_PROP_INTERESTING. Otherwise, return
@@ -5593,7 +5654,7 @@
value_range_t *vr;
size_t i = 0, j = 0, n;
tree vec;
- bool min_take_default, max_take_default;
+ bool take_default;
*taken_edge_p = NULL;
op = TREE_OPERAND (stmt, 0);
@@ -5618,27 +5679,23 @@
vec = SWITCH_LABELS (stmt);
n = TREE_VEC_LENGTH (vec);
- /* Find case label for minimum of the value range or the next one. */
- min_take_default = !find_case_label_index (vec, 0, vr->min, &i);
+ take_default = !find_case_label_range (vec, vr->min, vr->max, &i, &j);
- /* Find case label for maximum of the value range or the previous one. */
- max_take_default = !find_case_label_index (vec, i, vr->max, &j);
-
- /* Check if we reach the default label only. */
+ /* Check if the range spans no CASE_LABEL. If so, we only reach the default
+ label */
if (j < i)
- val = TREE_VEC_ELT (vec, n - 1);
- /* Check if we reach exactly one label and not the default label. */
- else if (i == j
- && !min_take_default
- && !max_take_default)
- val = TREE_VEC_ELT (vec, i);
+ {
+ gcc_assert (take_default);
+ val = TREE_VEC_ELT (vec, n - 1);
+ }
else
{
- /* Check if labels with index i to j are all reaching the same label.
- If we don't hit a single case label only, the default case also has
- to branch to the same label. */
+ /* Check if labels with index i to j and maybe the default label
+ are all reaching the same label. */
+
val = TREE_VEC_ELT (vec, i);
- if (CASE_LABEL (TREE_VEC_ELT (vec, n - 1)) != CASE_LABEL (val))
+ if (take_default
+ && CASE_LABEL (TREE_VEC_ELT (vec, n - 1)) != CASE_LABEL (val))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " not a single destination for this "
@@ -6323,33 +6380,8 @@
/* Find case label for min/max of the value range. */
vec = SWITCH_LABELS (stmt);
n = TREE_VEC_LENGTH (vec);
- take_default = !find_case_label_index (vec, 0, vr->min, &i);
- take_default |= !find_case_label_index (vec, i, vr->max, &j);
+ take_default = !find_case_label_range (vec, vr->min, vr->max, &i, &j);
- /* If the case label range is continuous, we do not need to
- preserve the default case label. Verify that. */
- if (!take_default && j > i)
- {
- tree low, high;
- size_t k;
-
- high = CASE_LOW (TREE_VEC_ELT (vec, i));
- if (CASE_HIGH (TREE_VEC_ELT (vec, i)))
- high = CASE_HIGH (TREE_VEC_ELT (vec, i));
- for (k = i + 1; k <= j; ++k)
- {
- low = CASE_LOW (TREE_VEC_ELT (vec, k));
- if (!integer_onep (int_const_binop (MINUS_EXPR, low, high, 0)))
- {
- take_default = true;
- break;
- }
- high = low;
- if (CASE_HIGH (TREE_VEC_ELT (vec, k)))
- high = CASE_HIGH (TREE_VEC_ELT (vec, k));
- }
- }
-
/* Bail out if this is just all edges taken. */
if (i == 0
&& j == n - 2
next prev parent reply other threads:[~2008-04-16 11:40 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-03-28 18:53 Richard Guenther
2008-04-02 12:21 ` Diego Novillo
2008-04-14 6:02 ` Rafael Espindola
2008-04-14 9:11 ` Richard Guenther
2008-04-15 9:15 ` Rafael Espindola
2008-04-15 9:18 ` Richard Guenther
2008-04-16 8:11 ` Rafael Espindola
2008-04-16 8:26 ` Rafael Espindola
2008-04-16 10:08 ` Richard Guenther
2008-04-16 12:32 ` Rafael Espindola [this message]
2008-04-16 12:43 ` Richard Guenther
2008-04-16 14:06 ` Rafael Espindola
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=38a0d8450804160439k678281f7wc4f6ca74990ff3fd@mail.gmail.com \
--to=espindola@google.com \
--cc=dnovillo@google.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=rguenther@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).