[PATCH] Fix Fortran aliasing problem with EQUIVALENCE
Jakub Jelinek
jakub@redhat.com
Wed Mar 22 22:36:00 GMT 2006
Hi!
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18518#c1 testcase is miscompiled
with GCC 4.1 and trunk at least on i?86 and x86_64 with -O2.
The scheduler swaps write into DMACH(1) with read from SMALL(1):
(insn 616 22 617 3 (set (reg:DI 1 dx)
(const_int 4801453603149578240 [0x42a2309ce5400000])) 81 {*movdi_1_rex64} (nil)
(nil))
(insn 617 616 26 3 (set (mem/s:DI (symbol_ref:DI ("equiv.0.1269") [flags 0x2] <var_decl 0x2b68b516cb00 equiv.0>) [9 equiv.0.dmach+0 S8 A64])
(reg:DI 1 dx)) 81 {*movdi_1_rex64} (nil)
(expr_list:REG_DEAD (reg:DI 1 dx)
(nil)))
(insn:HI 26 617 27 3 (set (reg:SI 0 ax [orig:76 D.1316 ] [76])
(mem/s:SI (symbol_ref:DI ("equiv.0.1269") [flags 0x2] <var_decl 0x2b68b516cb00 equiv.0>) [2 equiv.0.small+0 S4 A64])) 40 {*movsi_1} (nil)
(nil))
becomes after sched2 pass:
(insn:TI 26 22 616 3 (set (reg:SI 0 ax [orig:76 D.1316 ] [76])
(mem/s:SI (symbol_ref:DI ("equiv.0.1269") [flags 0x2] <var_decl 0x2b68b516cb00 equiv.0>) [2 equiv.0.small+0 S4 A64])) 40 {*movsi_1} (nil)
(nil))
(insn 616 26 617 3 (set (reg:DI 1 dx)
(const_int 4801453603149578240 [0x42a2309ce5400000])) 81 {*movdi_1_rex64} (nil)
(nil))
(insn:TI 617 616 27 3 (set (mem/s:DI (symbol_ref:DI ("equiv.0.1269") [flags 0x2] <var_decl 0x2b68b516cb00 equiv.0>) [9 equiv.0.dmach+0 S8 A64])
(reg:DI 1 dx)) 81 {*movdi_1_rex64} (nil)
(expr_list:REG_DEAD (reg:DI 1 dx)
(nil)))
That's because equiv.0.dmach and equiv.0.small use different alias sets (2
vs. 9). C/C++ in this case uses alias set 0 and I think Fortran should do
the same. If it is a component access through UNION_TYPE in Fortran, we
know it is either access to EQUIVALENCEd variable (which can't have POINTER
attribute nor be a CRAY POINTEE fortunately), or mixed entry master return
value. In both cases we want to allow type-punning.
Ok for trunk (and obviously modified patch for 4.1)?
I'm not including a testcase, because I don't know if we can put netlib
code in gcc testsuite and I haven't managed to distill a smaller testcase
from it (as it is scheduling related, so highly sensitive to the content of
the whole function).
Jakub
-------------- next part --------------
2006-03-22 Jakub Jelinek <jakub@redhat.com>
* f95-lang.c (gfc_get_alias_set): New function.
(LANG_HOOKS_GET_ALIAS_SET): Define.
--- gcc/fortran/f95-lang.c.jj 2006-02-16 08:22:59.000000000 +0100
+++ gcc/fortran/f95-lang.c 2006-03-22 22:38:28.000000000 +0100
@@ -99,6 +99,7 @@ void insert_block (tree);
static void gfc_clear_binding_stack (void);
static void gfc_be_parse_file (int);
static void gfc_expand_function (tree);
+static HOST_WIDE_INT gfc_get_alias_set (tree);
#undef LANG_HOOKS_NAME
#undef LANG_HOOKS_INIT
@@ -116,6 +117,7 @@ static void gfc_expand_function (tree);
#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
#undef LANG_HOOKS_CLEAR_BINDING_STACK
+#undef LANG_HOOKS_GET_ALIAS_SET
#undef LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#undef LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR
@@ -139,6 +141,7 @@ static void gfc_expand_function (tree);
#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE gfc_signed_or_unsigned_type
#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION gfc_expand_function
#define LANG_HOOKS_CLEAR_BINDING_STACK gfc_clear_binding_stack
+#define LANG_HOOKS_GET_ALIAS_SET gfc_get_alias_set
#define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE gfc_omp_privatize_by_reference
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING gfc_omp_predetermined_sharing
#define LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR gfc_omp_disregard_value_expr
@@ -694,6 +697,24 @@ gfc_mark_addressable (tree exp)
}
}
+/* Return the typed-based alias set for T, which may be an expression
+ or a type. Return -1 if we don't do anything special. */
+
+static HOST_WIDE_INT
+gfc_get_alias_set (tree t)
+{
+ tree u;
+
+ /* Permit type-punning when accessing an EQUIVALENCEd variable or
+ mixed type entry master's return value. */
+ for (u = t; handled_component_p (u); u = TREE_OPERAND (u, 0))
+ if (TREE_CODE (u) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
+ return 0;
+
+ return -1;
+}
+
/* press the big red button - garbage (ggc) collection is on */
int ggc_p = 1;
More information about the Fortran
mailing list