diff options
author | Craig Burley <craig@jcb-sc.com> | 1999-04-25 18:01:35 +0000 |
---|---|---|
committer | Craig Burley <burley@gcc.gnu.org> | 1999-04-25 14:01:35 -0400 |
commit | d6cd84e0365e7fc45d998c82a4bf82b12b34ae37 (patch) | |
tree | 06a70bfddeadb05621f45793665eaa03ca8eb1a1 /gcc | |
parent | 4433e33948b6cfeacbc9e98428dcfe0f23c4773b (diff) | |
download | gcc-d6cd84e0365e7fc45d998c82a4bf82b12b34ae37.zip gcc-d6cd84e0365e7fc45d998c82a4bf82b12b34ae37.tar.gz gcc-d6cd84e0365e7fc45d998c82a4bf82b12b34ae37.tar.bz2 |
fix assignment to partially-overlapped COMPLEX
From-SVN: r26625
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/f/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/f/com.c | 80 | ||||
-rw-r--r-- | gcc/f/version.c | 2 |
3 files changed, 90 insertions, 1 deletions
diff --git a/gcc/f/ChangeLog b/gcc/f/ChangeLog index 639cfab..1ebe291 100644 --- a/gcc/f/ChangeLog +++ b/gcc/f/ChangeLog @@ -1,3 +1,12 @@ +Sun Apr 25 20:55:10 1999 Craig Burley <craig@jcb-sc.com> + + Fix 19990325-0.f and 19990325-1.f: + * com.c (ffecom_possible_partial_overlap_): New function. + (ffecom_expand_let_stmt): Use it to determine whether to assign + to a COMPLEX operand through a temp. + + * version.c: Bump version. + Sat Apr 24 12:19:53 1999 Craig Burley <craig@jcb-sc.com> * expr.c (ffeexpr_finished_): Convert DATA implied-do diff --git a/gcc/f/com.c b/gcc/f/com.c index 9d05bab..3362ef3 100644 --- a/gcc/f/com.c +++ b/gcc/f/com.c @@ -1503,6 +1503,48 @@ ffecom_widest_expr_type_ (ffebld list) } #endif +/* Check whether a partial overlap between two expressions is possible. + + Can *starting* to write a portion of expr1 change the value + computed (perhaps already, *partially*) by expr2? + + Currently, this is a concern only for a COMPLEX expr1. But if it + isn't in COMMON or local EQUIVALENCE, since we don't support + aliasing of arguments, it isn't a concern. */ + +static bool +ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2) +{ + ffesymbol sym; + ffestorag st; + + switch (ffebld_op (expr1)) + { + case FFEBLD_opSYMTER: + sym = ffebld_symter (expr1); + break; + + case FFEBLD_opARRAYREF: + if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER) + return FALSE; + sym = ffebld_symter (ffebld_left (expr1)); + break; + + default: + return FALSE; + } + + if (ffesymbol_where (sym) != FFEINFO_whereCOMMON + && (ffesymbol_where (sym) != FFEINFO_whereLOCAL + || ! (st = ffesymbol_storage (sym)) + || ! ffestorag_parent (st))) + return FALSE; + + /* It's in COMMON or local EQUIVALENCE. */ + + return TRUE; +} + /* Check whether dest and source might overlap. ffebld versions of these might or might not be passed, will be NULL if not. @@ -11154,6 +11196,7 @@ ffecom_expand_let_stmt (ffebld dest, ffebld source) if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER) { bool dest_used; + tree assign_temp; /* This attempts to replicate the test below, but must not be true when the test below is false. (Always err on the side @@ -11174,6 +11217,22 @@ ffecom_expand_let_stmt (ffebld dest, ffebld source) ffecom_prepare_expr_w (NULL_TREE, dest); + /* For COMPLEX assignment like C1=C2, if partial overlap is possible, + create a temporary through which the assignment is to take place, + since MODIFY_EXPR doesn't handle partial overlap properly. */ + if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX + && ffecom_possible_partial_overlap_ (dest, source)) + { + assign_temp = ffecom_make_tempvar ("complex_let", + ffecom_tree_type + [ffebld_basictype (dest)] + [ffebld_kindtype (dest)], + FFETARGET_charactersizeNONE, + -1); + } + else + assign_temp = NULL_TREE; + ffecom_prepare_end (); dest_tree = ffecom_expr_w (NULL_TREE, dest); @@ -11195,6 +11254,27 @@ ffecom_expand_let_stmt (ffebld dest, ffebld source) if (dest_used) expr_tree = source_tree; + else if (assign_temp) + { +#ifdef MOVE_EXPR + /* The back end understands a conceptual move (evaluate source; + store into dest), so use that, in case it can determine + that it is going to use, say, two registers as temporaries + anyway. So don't use the temp (and someday avoid generating + it, once this code starts triggering regularly). */ + expr_tree = ffecom_2s (MOVE_EXPR, void_type_node, + dest_tree, + source_tree); +#else + expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node, + assign_temp, + source_tree); + expand_expr_stmt (expr_tree); + expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node, + dest_tree, + assign_temp); +#endif + } else expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node, dest_tree, diff --git a/gcc/f/version.c b/gcc/f/version.c index e431055..da8caa5 100644 --- a/gcc/f/version.c +++ b/gcc/f/version.c @@ -1 +1 @@ -const char *ffe_version_string = "0.5.24-19990424"; +const char *ffe_version_string = "0.5.24-19990425"; |