------- 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