aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2010-09-10 01:28:27 +0200
committerMartin Jambor <jamborm@gcc.gnu.org>2010-09-10 01:28:27 +0200
commitfffe1e4064df4724b2e5e7c57d8e478bd3ab22fe (patch)
treed7ee5188de8d6ec3eb3b71b2622e67165443cd84
parent508371fe2189f852f4c63ec5e7e312c25bb366c4 (diff)
downloadgcc-fffe1e4064df4724b2e5e7c57d8e478bd3ab22fe.zip
gcc-fffe1e4064df4724b2e5e7c57d8e478bd3ab22fe.tar.gz
gcc-fffe1e4064df4724b2e5e7c57d8e478bd3ab22fe.tar.bz2
re PR tree-optimization/44972 (ICE: in load_assign_lhs_subreplacements, at tree-sra.c:2475)
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. * testsuite/g++.dg/torture/pr34850.C: Remove expected warning. From-SVN: r164135
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/ipa-prop.c99
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr34850.C2
4 files changed, 80 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 38e51f8..1128ae9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 99e59b0..0ad7324 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -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),
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fbbbd56..0478d9a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/torture/pr34850.C b/gcc/testsuite/g++.dg/torture/pr34850.C
index 88df5a3..05f895c 100644
--- a/gcc/testsuite/g++.dg/torture/pr34850.C
+++ b/gcc/testsuite/g++.dg/torture/pr34850.C
@@ -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) {