From ae788515d2b28952fdee5a83b010667dc9285732 Mon Sep 17 00:00:00 2001
From: Eric Botcazou <ebotcazou@adacore.com>
Date: Sun, 14 Nov 2010 11:24:47 +0000
Subject: [PATCH] re PR tree-optimization/45722 (FAIL:
 gcc.c-torture/execute/20040709-2.c execution at -O1 and -Os)

	PR tree-optimization/45722
	* tree-sra.c (build_ref_for_model): Always build a COMPONENT_REF if
	this is a reference to a component.
	* ipa-prop.c (ipa_get_member_ptr_load_param): Accept COMPONENT_REF.
	(ipa_note_param_call): Adjust comment.

From-SVN: r166731
---
 gcc/ChangeLog  |  8 ++++++++
 gcc/ipa-prop.c | 32 ++++++++++++++++++++++++++++----
 gcc/tree-sra.c |  7 ++-----
 3 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d1aef39f1752..d4793931a372 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2010-11-14  Eric Botcazou  <ebotcazou@adacore.com>
+
+	PR tree-optimization/45722
+	* tree-sra.c (build_ref_for_model): Always build a COMPONENT_REF if
+	this is a reference to a component.
+	* ipa-prop.c (ipa_get_member_ptr_load_param): Accept COMPONENT_REF.
+	(ipa_note_param_call): Adjust comment.
+
 2010-11-14  Richard Sandiford  <rdsandiford@googlemail.com>
 
 	* config/mips/mips.c (machine_function): Remove
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 473f483ad3dc..7c7df56e6f49 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -918,10 +918,15 @@ ipa_compute_jump_functions (struct cgraph_node *node,
 static tree
 ipa_get_member_ptr_load_param (tree rhs, bool use_delta)
 {
-  tree rec, ref_offset, fld_offset;
-  tree ptr_field;
-  tree delta_field;
+  tree rec, ref_field, ref_offset, fld, fld_offset, ptr_field, delta_field;
 
+  if (TREE_CODE (rhs) == COMPONENT_REF)
+    {
+      ref_field = TREE_OPERAND (rhs, 1);
+      rhs = TREE_OPERAND (rhs, 0);
+    }
+  else
+    ref_field = NULL_TREE;
   if (TREE_CODE (rhs) != MEM_REF)
     return NULL_TREE;
   rec = TREE_OPERAND (rhs, 0);
@@ -933,6 +938,20 @@ ipa_get_member_ptr_load_param (tree rhs, bool use_delta)
     return NULL_TREE;
 
   ref_offset = TREE_OPERAND (rhs, 1);
+
+  if (ref_field)
+    {
+      if (integer_nonzerop (ref_offset))
+	return NULL_TREE;
+
+      if (use_delta)
+	fld = delta_field;
+      else
+	fld = ptr_field;
+
+      return ref_field == fld ? rec : NULL_TREE;
+    }
+
   if (use_delta)
     fld_offset = byte_position (delta_field);
   else
@@ -1004,11 +1023,16 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt,
    pattern of such a call.  An example of such a pattern is the gimple dump
    below, the call is on the last line:
 
+     <bb 2>:
+       f$__delta_5 = f.__delta;
+       f$__pfn_24 = f.__pfn;
+
+   or
      <bb 2>:
        f$__delta_5 = MEM[(struct  *)&f];
        f$__pfn_24 = MEM[(struct  *)&f + 4B];
 
-     ...
+   and a few lines below:
 
      <bb 5>
        D.2496_3 = (int) f$__pfn_24;
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index be1b45e6b9ca..88199f131aee 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -1391,7 +1391,7 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
 
 /* Construct a memory reference to a part of an aggregate BASE at the given
    OFFSET and of the same type as MODEL.  In case this is a reference to a
-   bit-field, the function will replicate the last component_ref of model's
+   component, the function will replicate the last COMPONENT_REF of model's
    expr to access it.  GSI and INSERT_AFTER have the same meaning as in
    build_ref_for_offset.  */
 
@@ -1400,12 +1400,9 @@ build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
 		     struct access *model, gimple_stmt_iterator *gsi,
 		     bool insert_after)
 {
-  if (TREE_CODE (model->expr) == COMPONENT_REF
-      && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
+  if (TREE_CODE (model->expr) == COMPONENT_REF)
     {
-      /* This access represents a bit-field.  */
       tree t, exp_type;
-
       offset -= int_bit_position (TREE_OPERAND (model->expr, 1));
       exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
       t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);