------- Comment #6 from jsjodin at gcc dot gnu dot org 2007-12-03 15:41 -------
> Indeed the extra load disappeared when with the patch. The store did not get
> deleted as expected. I looked at the differences between the good and bad
> case.
After doing some more investigation an attempt to fix the problem was done in
the value numbering pass. By using the size and a unique type for the size to
compute the value number it not longer matters which union that is accessed,
only the number of bits that are read/written. This gives good code test.cpp,
however the problem with this approach is that in FRE the different types
result in a cast, but it should really be a reinterpretation of the bits
(different types, same bit pattern). The small example below gives: int: -1,
float: -1.000000 which is wrong. The expected result is: int: -1, float: nan
The solution would be to make the reinterpretation possible somehow.
Simple test:
---------------------------------------------------------------
#include <stdio.h>
union foo {
int i;
float f;
} bar;
int main()
{
int x = 0xFFFFFFFF;
float y = 0.0;
bar.i = x;
y = bar.f;
printf("int: %d, float: %f\n", bar.i, bar.f);
return 0;
}
-----------------------------------------------------------------
Index: tree-ssa-sccvn.c
===================================================================
--- tree-ssa-sccvn.c (revision 130099)
+++ tree-ssa-sccvn.c (working copy)
@@ -456,6 +456,33 @@ shared_vuses_from_stmt (tree stmt)
return shared_lookup_vops;
}
+
+static tree get_generic_type_node_from_size(int size)
+{
+ tree result = NULL;
+ switch(size)
+ {
+ case 8:
+ result = unsigned_intQI_type_node;
+ break;
+ case 16:
+ result = unsigned_intHI_type_node;
+ break;
+ case 32:
+ result = unsigned_intSI_type_node;
+ break;
+ case 64:
+ result = unsigned_intDI_type_node;
+ break;
+ case 128:
+ result = unsigned_intTI_type_node;
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
/* Copy the operations present in load/store/call REF into RESULT, a vector of
vn_reference_op_s's. */
@@ -521,7 +548,23 @@ copy_reference_ops_from_ref (tree ref, V
break;
case COMPONENT_REF:
/* Record field as operand. */
- temp.op0 = TREE_OPERAND (ref, 1);
+ {
+ tree aggregate = TREE_OPERAND (ref, 0);
+ tree aggregate_type = TREE_TYPE(aggregate);
+ tree field_decl = TREE_OPERAND (ref, 1);
+ tree field_decl_type = TREE_TYPE(field_decl);
+ tree field_decl_type_size = TYPE_SIZE(field_decl_type);
+ if (TREE_CODE (aggregate_type) == UNION_TYPE
+ && TREE_CODE (field_decl_type_size) == INTEGER_CST)
+ {
+ temp.op0 = field_decl_type_size;
+ temp.type =
get_generic_type_node_from_size(TREE_INT_CST_LOW(field_decl_type_size)) != NULL
+ ?
get_generic_type_node_from_size(TREE_INT_CST_LOW(field_decl_type_size))
+ : temp.type;
+ } else {
+ temp.op0 = TREE_OPERAND (ref, 1);
+ }
+ }
break;
case ARRAY_RANGE_REF:
case ARRAY_REF:
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34043