2010-09-10 Martin Jambor <mjambor@suse.cz>
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Sep 2010 23:28:27 +0000 (23:28 +0000)
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Sep 2010 23:28:27 +0000 (23:28 +0000)
PR tree-optimization/44972
* ipa-prop.c (ipa_modify_call_arguments): Build MEM_REF instead of
calling build_ref_for_offset.

* testsuite/g++.dg/torture/pr34850.C: Remove expected warning.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164135 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ipa-prop.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr34850.C

index 38e51f8..1128ae9 100644 (file)
@@ -1,3 +1,9 @@
+2010-09-10  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/44972
+       * ipa-prop.c (ipa_modify_call_arguments): Build MEM_REF instead of
+       calling build_ref_for_offset.
+
 2010-09-09  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
 
         * config/arm/bpabi.h (BE8_LINK_SPEC): Handle Cortex-a15.
index 99e59b0..0ad7324 100644 (file)
@@ -2153,40 +2153,77 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
        }
       else if (!adj->remove_param)
        {
-         tree expr, orig_expr;
-         bool allow_ptr, repl_found;
-
-         orig_expr = expr = gimple_call_arg (stmt, adj->base_index);
-         if (TREE_CODE (expr) == ADDR_EXPR)
-           {
-             allow_ptr = false;
-             expr = TREE_OPERAND (expr, 0);
-           }
+         tree expr, base, off;
+         location_t loc;
+
+         /* We create a new parameter out of the value of the old one, we can
+            do the following kind of transformations:
+
+            - A scalar passed by reference is converted to a scalar passed by
+               value.  (adj->by_ref is false and the type of the original
+               actual argument is a pointer to a scalar).
+
+             - A part of an aggregate is passed instead of the whole aggregate.
+               The part can be passed either by value or by reference, this is
+               determined by value of adj->by_ref.  Moreover, the code below
+               handles both situations when the original aggregate is passed by
+               value (its type is not a pointer) and when it is passed by
+               reference (it is a pointer to an aggregate).
+
+            When the new argument is passed by reference (adj->by_ref is true)
+            it must be a part of an aggregate and therefore we form it by
+            simply taking the address of a reference inside the original
+            aggregate.  */
+
+         gcc_checking_assert (adj->offset % BITS_PER_UNIT == 0);
+         base = gimple_call_arg (stmt, adj->base_index);
+         loc = EXPR_LOCATION (base);
+
+         if (TREE_CODE (base) == ADDR_EXPR
+             && DECL_P (TREE_OPERAND (base, 0)))
+           off = build_int_cst (reference_alias_ptr_type (base),
+                                adj->offset / BITS_PER_UNIT);
+         else if (TREE_CODE (base) != ADDR_EXPR
+                  && POINTER_TYPE_P (TREE_TYPE (base)))
+           off = build_int_cst (TREE_TYPE (base), adj->offset / BITS_PER_UNIT);
          else
-           allow_ptr = true;
-
-         repl_found = build_ref_for_offset (&expr, TREE_TYPE (expr),
-                                            adj->offset, adj->type,
-                                            allow_ptr);
-         if (repl_found)
            {
-             if (adj->by_ref)
-               expr = build_fold_addr_expr (expr);
-           }
-         else
-           {
-             tree ptrtype = build_pointer_type (adj->type);
-             expr = orig_expr;
-             if (!POINTER_TYPE_P (TREE_TYPE (expr)))
-               expr = build_fold_addr_expr (expr);
-             if (!useless_type_conversion_p (ptrtype, TREE_TYPE (expr)))
-               expr = fold_convert (ptrtype, expr);
-             expr = fold_build2 (POINTER_PLUS_EXPR, ptrtype, expr,
-                                 build_int_cst (sizetype,
-                                                adj->offset / BITS_PER_UNIT));
-             if (!adj->by_ref)
-               expr = fold_build1 (INDIRECT_REF, adj->type, expr);
+             HOST_WIDE_INT base_offset;
+             tree prev_base;
+
+             if (TREE_CODE (base) == ADDR_EXPR)
+               base = TREE_OPERAND (base, 0);
+             prev_base = base;
+             base = get_addr_base_and_unit_offset (base, &base_offset);
+             /* Aggregate arguments can have non-invariant addresses.  */
+             if (!base)
+               {
+                 base = build_fold_addr_expr (prev_base);
+                 off = build_int_cst (reference_alias_ptr_type (prev_base),
+                                      adj->offset / BITS_PER_UNIT);
+               }
+             else if (TREE_CODE (base) == MEM_REF)
+               {
+                 off = build_int_cst (TREE_TYPE (TREE_OPERAND (base,1)),
+                                      base_offset
+                                      + adj->offset / BITS_PER_UNIT);
+                 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1),
+                                        off, 0);
+                 base = TREE_OPERAND (base, 0);
+               }
+             else
+               {
+                 off = build_int_cst (reference_alias_ptr_type (base),
+                                      base_offset
+                                      + adj->offset / BITS_PER_UNIT);
+                 base = build_fold_addr_expr (base);
+               }
            }
+
+         expr = fold_build2_loc (loc, MEM_REF, adj->type, base, off);
+         if (adj->by_ref)
+           expr = build_fold_addr_expr (expr);
+
          expr = force_gimple_operand_gsi (&gsi, expr,
                                           adj->by_ref
                                           || is_gimple_reg_type (adj->type),
index fbbbd56..0478d9a 100644 (file)
@@ -1,3 +1,8 @@
+2010-09-10  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/44972
+       * g++.dg/torture/pr34850.C: Remove expected warning.
+
 2010-09-09  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        * gfortran.dg/dummy_optional_arg.f90: New test.
index 88df5a3..05f895c 100644 (file)
@@ -11,7 +11,7 @@ extern "C" {
     extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__, __artificial__))
     void * memset (void *__dest, int __ch, size_t __len) throw () {
        if (__builtin_constant_p (__len) && __len == 0)
-           __warn_memset_zero_len (); /* { dg-warning "" } */
+           __warn_memset_zero_len ();
     }
 }
 inline void clear_mem(void* ptr, u32bit n)    {