* [gfortran,patch] Improve handling of character SELECT
@ 2007-07-11 21:37 FX Coudert
2007-07-11 21:59 ` Andrew Pinski
2007-07-15 8:58 ` Janne Blomqvist
0 siblings, 2 replies; 4+ messages in thread
From: FX Coudert @ 2007-07-11 21:37 UTC (permalink / raw)
To: fortran@gcc.gnu.org List, gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 879 bytes --]
The patch attached is a partial rewrite of the translation of SELECT
for character types. Currently, we generate a blocks of code for each
case, along with a label and a list of the cases; a library function
is called and it returns the address of the label that we will jump
to. This use of jumps (GOTO_EXPR) is apparently hard on the middle-
end (probably causing missed-optimizations, and at least preventing
it to correctly understand what variables are initialized: see PR
32035). Andrew Pinski suggested that we can use a SWITCH_EXPR instead
(thanks Andrew for the analysis!). This is what my patch does, by
assiging an integer value to each case, making the library function
return an integer value and using a switch to select the appropriate
code block to execute.
Bootstrapped and regtested on x86_64-linux, OK for mainline?
:ADDPATCH fortran:
[-- Attachment #2: select_char.ChangeLog --]
[-- Type: application/octet-stream, Size: 602 bytes --]
2007-07-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR fortran/32035
* trans-stmt.c (gfc_trans_character_select): Replace the
mechanism with labels by a SWITCH_EXPR.
* trans-decl.c (gfc_build_builtin_function_decls): Change
return type for select_string.
2007-07-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR fortran/32035
* runtime/select.c (select_string): Adjust prototype and function
so that the return value is an integer, not a pointer.
2007-07-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR fortran/32035
* gfortran.dg/select_char_1.f90: New test.
[-- Attachment #3: select_char.diff --]
[-- Type: application/octet-stream, Size: 8322 bytes --]
Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c (revision 126524)
+++ gcc/fortran/trans-stmt.c (working copy)
@@ -1319,13 +1319,13 @@ gfc_trans_logical_select (gfc_code * cod
static tree
gfc_trans_character_select (gfc_code *code)
{
- tree init, node, end_label, tmp, type, *labels;
- tree case_label;
+ tree init, node, end_label, tmp, type, case_num, label;
+ tree gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind);
stmtblock_t block, body;
gfc_case *cp, *d;
gfc_code *c;
gfc_se se;
- int i, n;
+ int n;
static tree select_struct;
static tree ss_string1, ss_string1_len;
@@ -1351,7 +1351,7 @@ gfc_trans_character_select (gfc_code *co
ADD_FIELD (string2, pchar_type_node);
ADD_FIELD (string2_len, gfc_int4_type_node);
- ADD_FIELD (target, pvoid_type_node);
+ ADD_FIELD (target, gfc_c_int_type_node);
#undef ADD_FIELD
gfc_finish_type (select_struct);
@@ -1365,20 +1365,6 @@ gfc_trans_character_select (gfc_code *co
for (d = cp; d; d = d->right)
d->n = n++;
- if (n != 0)
- labels = gfc_getmem (n * sizeof (tree));
- else
- labels = NULL;
-
- for(i = 0; i < n; i++)
- {
- labels[i] = gfc_build_label_decl (NULL_TREE);
- TREE_USED (labels[i]) = 1;
- /* TODO: The gimplifier should do this for us, but it has
- inadequacies when dealing with static initializers. */
- FORCED_LABEL (labels[i]) = 1;
- }
-
end_label = gfc_build_label_decl (NULL_TREE);
/* Generate the body */
@@ -1389,7 +1375,10 @@ gfc_trans_character_select (gfc_code *co
{
for (d = c->ext.case_list; d; d = d->next)
{
- tmp = build1_v (LABEL_EXPR, labels[d->n]);
+ label = gfc_build_label_decl (NULL_TREE);
+ tmp = build3 (CASE_LABEL_EXPR, void_type_node,
+ build_int_cst (NULL_TREE, d->n),
+ build_int_cst (NULL_TREE, d->n), label);
gfc_add_expr_to_block (&body, tmp);
}
@@ -1402,9 +1391,8 @@ gfc_trans_character_select (gfc_code *co
/* Generate the structure describing the branches */
init = NULL_TREE;
- i = 0;
- for(d = cp; d; d = d->right, i++)
+ for(d = cp; d; d = d->right)
{
node = NULL_TREE;
@@ -1437,8 +1425,8 @@ gfc_trans_character_select (gfc_code *co
node = tree_cons (ss_string2_len, se.string_length, node);
}
- tmp = gfc_build_addr_expr (pvoid_type_node, labels[i]);
- node = tree_cons (ss_target, tmp, node);
+ node = tree_cons (ss_target, build_int_cst (gfc_c_int_type_node, d->n),
+ node);
tmp = build_constructor_from_list (select_struct, nreverse (node));
init = tree_cons (NULL_TREE, tmp, init);
@@ -1462,33 +1450,27 @@ gfc_trans_character_select (gfc_code *co
/* Build the library call */
init = gfc_build_addr_expr (pvoid_type_node, init);
- tmp = gfc_build_addr_expr (pvoid_type_node, end_label);
gfc_init_se (&se, NULL);
gfc_conv_expr_reference (&se, code->expr);
gfc_add_block_to_block (&block, &se.pre);
- tmp = build_call_expr (gfor_fndecl_select_string, 5,
- init, build_int_cst (NULL_TREE, n),
- tmp, se.expr, se.string_length);
-
- case_label = gfc_create_var (TREE_TYPE (tmp), "case_label");
- gfc_add_modify_expr (&block, case_label, tmp);
+ tmp = build_call_expr (gfor_fndecl_select_string, 4, init,
+ build_int_cst (NULL_TREE, n), se.expr,
+ se.string_length);
+ case_num = gfc_create_var (gfc_c_int_type_node, "case_num");
+ gfc_add_modify_expr (&block, case_num, tmp);
gfc_add_block_to_block (&block, &se.post);
- tmp = build1 (GOTO_EXPR, void_type_node, case_label);
- gfc_add_expr_to_block (&block, tmp);
-
tmp = gfc_finish_block (&body);
+ tmp = build3_v (SWITCH_EXPR, case_num, tmp, NULL_TREE);
gfc_add_expr_to_block (&block, tmp);
+
tmp = build1_v (LABEL_EXPR, end_label);
gfc_add_expr_to_block (&block, tmp);
- if (n != 0)
- gfc_free (labels);
-
return gfc_finish_block (&block);
}
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c (revision 126524)
+++ gcc/fortran/trans-decl.c (working copy)
@@ -2334,7 +2334,7 @@ gfc_build_builtin_function_decls (void)
gfor_fndecl_select_string =
gfc_build_library_function_decl (get_identifier (PREFIX("select_string")),
- pvoid_type_node, 0);
+ gfc_c_int_type_node, 0);
gfor_fndecl_runtime_error =
gfc_build_library_function_decl (get_identifier (PREFIX("runtime_error")),
Index: libgfortran/runtime/select.c
===================================================================
--- libgfortran/runtime/select.c (revision 126524)
+++ libgfortran/runtime/select.c (working copy)
@@ -35,28 +35,28 @@ typedef struct
int low_len;
char *high;
int high_len;
- void *address;
+ int address;
}
select_struct;
-extern void * select_string (select_struct *table, int table_len,
- void *default_jump, const char *selector,
- int selector_len);
+extern int select_string (select_struct *table, int table_len,
+ const char *selector, int selector_len);
export_proto(select_string);
/* select_string()-- Given a selector string and a table of
* select_struct structures, return the address to jump to. */
-void *
-select_string (select_struct *table, int table_len, void *default_jump,
- const char *selector, int selector_len)
+int
+select_string (select_struct *table, int table_len, const char *selector,
+ int selector_len)
{
select_struct *t;
int i, low, high, mid;
+ int default_jump;
if (table_len == 0)
- return default_jump;
+ return -1;
/* Record the default address if present */
Index: gcc/testsuite/gfortran.dg/select_char_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/select_char_1.f90 (revision 0)
+++ gcc/testsuite/gfortran.dg/select_char_1.f90 (revision 0)
@@ -0,0 +1,76 @@
+integer function char_select (s)
+ character(len=*), intent(in) :: s
+
+ select case(s)
+ case ("foo")
+ char_select = 1
+ case ("bar", "gee")
+ char_select = 2
+ case ("111", "999")
+ char_select = 3
+ case ("1024", "1900")
+ char_select = 4
+ case ("12", "17890")
+ char_select = 5
+ case default
+ char_select = -1
+ end select
+end function char_select
+
+integer function char_select2 (s)
+ character(len=*), intent(in) :: s
+
+ char_select2 = -1
+ select case(s)
+ case ("foo")
+ char_select2 = 1
+ case ("bar", "gee")
+ char_select2 = 2
+ case ("111", "999")
+ char_select2 = 3
+ case ("1024", "1900")
+ char_select2 = 4
+ case ("12", "17890")
+ char_select2 = 5
+ end select
+end function char_select2
+
+
+program test
+ interface
+ integer function char_select (s)
+ character(len=*), intent(in) :: s
+ end function char_select
+ integer function char_select2 (s)
+ character(len=*), intent(in) :: s
+ end function char_select2
+ end interface
+
+ if (char_select("foo") /= 1) call abort
+ if (char_select("foo ") /= 1) call abort
+ if (char_select("foo2 ") /= -1) call abort
+ if (char_select("bar") /= 2) call abort
+ if (char_select("gee") /= 2) call abort
+ if (char_select("000") /= -1) call abort
+ if (char_select("101") /= -1) call abort
+ if (char_select("109") /= -1) call abort
+ if (char_select("111") /= 3) call abort
+ if (char_select("254") /= -1) call abort
+ if (char_select("999") /= 3) call abort
+ if (char_select("9989") /= -1) call abort
+ if (char_select("1882") /= -1) call abort
+
+ if (char_select2("foo") /= 1) call abort
+ if (char_select2("foo ") /= 1) call abort
+ if (char_select2("foo2 ") /= -1) call abort
+ if (char_select2("bar") /= 2) call abort
+ if (char_select2("gee") /= 2) call abort
+ if (char_select2("000") /= -1) call abort
+ if (char_select2("101") /= -1) call abort
+ if (char_select2("109") /= -1) call abort
+ if (char_select2("111") /= 3) call abort
+ if (char_select2("254") /= -1) call abort
+ if (char_select2("999") /= 3) call abort
+ if (char_select2("9989") /= -1) call abort
+ if (char_select2("1882") /= -1) call abort
+end program test
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [gfortran,patch] Improve handling of character SELECT
2007-07-11 21:37 [gfortran,patch] Improve handling of character SELECT FX Coudert
@ 2007-07-11 21:59 ` Andrew Pinski
2007-07-15 8:58 ` Janne Blomqvist
1 sibling, 0 replies; 4+ messages in thread
From: Andrew Pinski @ 2007-07-11 21:59 UTC (permalink / raw)
To: FX Coudert; +Cc: fortran@gcc.gnu.org List, gcc-patches List
On 7/11/07, FX Coudert <fxcoudert@gmail.com> wrote:
> The patch attached is a partial rewrite of the translation of SELECT
> for character types. Currently, we generate a blocks of code for each
> case, along with a label and a list of the cases; a library function
> is called and it returns the address of the label that we will jump
> to. This use of jumps (GOTO_EXPR) is apparently hard on the middle-
> end (probably causing missed-optimizations, and at least preventing
> it to correctly understand what variables are initialized: see PR
> 32035). Andrew Pinski suggested that we can use a SWITCH_EXPR instead
> (thanks Andrew for the analysis!). This is what my patch does, by
> assiging an integer value to each case, making the library function
> return an integer value and using a switch to select the appropriate
> code block to execute.
This also works around the tree optimizer problem listed as PR 32720.
Thanks,
Andrew Pinski
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [gfortran,patch] Improve handling of character SELECT
2007-07-11 21:37 [gfortran,patch] Improve handling of character SELECT FX Coudert
2007-07-11 21:59 ` Andrew Pinski
@ 2007-07-15 8:58 ` Janne Blomqvist
2007-07-27 15:06 ` FX Coudert
1 sibling, 1 reply; 4+ messages in thread
From: Janne Blomqvist @ 2007-07-15 8:58 UTC (permalink / raw)
To: FX Coudert; +Cc: fortran@gcc.gnu.org List, gcc-patches List
:REVIEWMAIL:
On 7/12/07, FX Coudert <fxcoudert@gmail.com> wrote:
> The patch attached is a partial rewrite of the translation of SELECT
> for character types. Currently, we generate a blocks of code for each
> case, along with a label and a list of the cases; a library function
> is called and it returns the address of the label that we will jump
> to. This use of jumps (GOTO_EXPR) is apparently hard on the middle-
> end (probably causing missed-optimizations, and at least preventing
> it to correctly understand what variables are initialized: see PR
> 32035). Andrew Pinski suggested that we can use a SWITCH_EXPR instead
> (thanks Andrew for the analysis!). This is what my patch does, by
> assiging an integer value to each case, making the library function
> return an integer value and using a switch to select the appropriate
> code block to execute.
>
> Bootstrapped and regtested on x86_64-linux, OK for mainline?
Ok.
Please also put a note to PR 32720 that although your patch fixes the
regression, the underlying middle-end bug is still there.
--
Janne Blomqvist
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [gfortran,patch] Improve handling of character SELECT
2007-07-15 8:58 ` Janne Blomqvist
@ 2007-07-27 15:06 ` FX Coudert
0 siblings, 0 replies; 4+ messages in thread
From: FX Coudert @ 2007-07-27 15:06 UTC (permalink / raw)
To: Janne Blomqvist; +Cc: fortran@gcc.gnu.org List, gcc-patches List
Committed as rev. 126978: http://gcc.gnu.org/viewcvs?
view=rev&revision=126978
Thanks for the review,
FX
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-07-27 14:28 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-11 21:37 [gfortran,patch] Improve handling of character SELECT FX Coudert
2007-07-11 21:59 ` Andrew Pinski
2007-07-15 8:58 ` Janne Blomqvist
2007-07-27 15:06 ` FX Coudert
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).