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

Reply via email to