aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2008-12-03 13:27:48 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2008-12-03 13:27:48 +0100
commitff1fe457370d6f33071747b0dfd1b76dff7e247a (patch)
tree5ba418443623690434ede1e71ba81639b49d733b
parentd5fdc62c3fe523b1104bcccaa3f66f7fa5298d9f (diff)
downloadgcc-ff1fe457370d6f33071747b0dfd1b76dff7e247a.zip
gcc-ff1fe457370d6f33071747b0dfd1b76dff7e247a.tar.gz
gcc-ff1fe457370d6f33071747b0dfd1b76dff7e247a.tar.bz2
re PR tree-optimization/37716 (ice for legal C++ code with -O2 on 20080926)
PR tree-optimization/37716 * tree-sra.c (sra_build_assignment): For scalar bitfield SRC construct all the needed operations as trees and gimplify_assign it to dst. * g++.dg/torture/pr37716.C: New test. From-SVN: r142392
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr37716.C56
-rw-r--r--gcc/tree-sra.c86
4 files changed, 90 insertions, 61 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3eef937..26e34ef 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,9 @@
2008-12-03 Jakub Jelinek <jakub@redhat.com>
+ PR tree-optimization/37716
+ * tree-sra.c (sra_build_assignment): For scalar bitfield SRC construct
+ all the needed operations as trees and gimplify_assign it to dst.
+
PR target/37610
* configure.ac (gcc_cv_readelf): Look for readelf.
(gcc_cv_as_cfi_advance_working): Check for working
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2d8b273..f12dbdb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2008-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/37716
+ * g++.dg/torture/pr37716.C: New test.
+
2008-12-03 Eric Botcazou <ebotcazou@adacore.com>
* gcc.dg/torture/pr37868.c: Skip on the SPARC.
diff --git a/gcc/testsuite/g++.dg/torture/pr37716.C b/gcc/testsuite/g++.dg/torture/pr37716.C
new file mode 100644
index 0000000..13b98d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr37716.C
@@ -0,0 +1,56 @@
+// PR tree-optimization/37716
+// { dg-do compile }
+
+struct A
+{
+ struct B
+ {
+ int a, b, c, d;
+ void *e[1];
+ };
+ B *d;
+ inline void **f1 (int i) const
+ {
+ return d->e + d->c + i;
+ }
+};
+
+template <typename T>
+struct C
+{
+ struct D
+ {
+ void *v;
+ inline T & f3 ()
+ {
+ return *reinterpret_cast <T *> (this);
+ }
+ };
+ union
+ {
+ A p;
+ A::B *d;
+ };
+ T & operator[](int i)
+ {
+ if (d->a != 1)
+ f2 ();
+ return reinterpret_cast <D *> (p.f1 (i))->f3 ();
+ }
+ void f2 ();
+ void f3 (int i, const T & t);
+};
+
+class E
+{
+ int e, f;
+};
+
+C <E> c;
+
+void
+foo (int x)
+{
+ E e = c[x];
+ c.f3 (x, e);
+}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 60330b1..3225d10 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -2158,9 +2158,10 @@ sra_build_assignment (tree dst, tree src)
if (scalar_bitfield_p (src))
{
tree var, shift, width;
- tree utype, stype, stmp, utmp, dtmp;
+ tree utype, stype;
bool unsignedp = (INTEGRAL_TYPE_P (TREE_TYPE (src))
? TYPE_UNSIGNED (TREE_TYPE (src)) : true);
+ struct gimplify_ctx gctx;
var = TREE_OPERAND (src, 0);
width = TREE_OPERAND (src, 1);
@@ -2191,28 +2192,15 @@ sra_build_assignment (tree dst, tree src)
else if (!TYPE_UNSIGNED (utype))
utype = unsigned_type_for (utype);
- stmp = make_rename_temp (stype, "SR");
-
/* Convert the base var of the BIT_FIELD_REF to the scalar type
we use for computation if we cannot use it directly. */
- if (!useless_type_conversion_p (stype, TREE_TYPE (var)))
- {
- if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
- stmt = gimple_build_assign (stmp, fold_convert (stype, var));
- else
- stmt = gimple_build_assign (stmp, fold_build1 (VIEW_CONVERT_EXPR,
- stype, var));
- gimple_seq_add_stmt (&seq, stmt);
- var = stmp;
- }
+ if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
+ var = fold_convert (stype, var);
+ else
+ var = fold_build1 (VIEW_CONVERT_EXPR, stype, var);
if (!integer_zerop (shift))
- {
- stmt = gimple_build_assign (stmp, fold_build2 (RSHIFT_EXPR, stype,
- var, shift));
- gimple_seq_add_stmt (&seq, stmt);
- var = stmp;
- }
+ var = fold_build2 (RSHIFT_EXPR, stype, var, shift);
/* If we need a masking operation, produce one. */
if (TREE_INT_CST_LOW (width) == TYPE_PRECISION (stype))
@@ -2222,24 +2210,11 @@ sra_build_assignment (tree dst, tree src)
tree one = build_int_cst_wide (stype, 1, 0);
tree mask = int_const_binop (LSHIFT_EXPR, one, width, 0);
mask = int_const_binop (MINUS_EXPR, mask, one, 0);
-
- stmt = gimple_build_assign (stmp, fold_build2 (BIT_AND_EXPR, stype,
- var, mask));
- gimple_seq_add_stmt (&seq, stmt);
- var = stmp;
+ var = fold_build2 (BIT_AND_EXPR, stype, var, mask);
}
/* After shifting and masking, convert to the target type. */
- utmp = stmp;
- if (!useless_type_conversion_p (utype, stype))
- {
- utmp = make_rename_temp (utype, "SR");
-
- stmt = gimple_build_assign (utmp, fold_convert (utype, var));
- gimple_seq_add_stmt (&seq, stmt);
-
- var = utmp;
- }
+ var = fold_convert (utype, var);
/* Perform sign extension, if required.
??? This should never be necessary. */
@@ -2250,40 +2225,29 @@ sra_build_assignment (tree dst, tree src)
size_binop (MINUS_EXPR, width,
bitsize_int (1)), 0);
- stmt = gimple_build_assign (utmp, fold_build2 (BIT_XOR_EXPR, utype,
- var, signbit));
- gimple_seq_add_stmt (&seq, stmt);
-
- stmt = gimple_build_assign (utmp, fold_build2 (MINUS_EXPR, utype,
- utmp, signbit));
- gimple_seq_add_stmt (&seq, stmt);
-
- var = utmp;
+ var = fold_build2 (BIT_XOR_EXPR, utype, var, signbit);
+ var = fold_build2 (MINUS_EXPR, utype, var, signbit);
}
/* fold_build3 (BIT_FIELD_REF, ...) sometimes returns a cast. */
STRIP_NOPS (dst);
/* Finally, move and convert to the destination. */
- if (!useless_type_conversion_p (TREE_TYPE (dst), TREE_TYPE (var)))
- {
- if (INTEGRAL_TYPE_P (TREE_TYPE (dst)))
- var = fold_convert (TREE_TYPE (dst), var);
- else
- var = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dst), var);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (dst)))
+ var = fold_convert (TREE_TYPE (dst), var);
+ else
+ var = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dst), var);
- /* If the destination is not a register the conversion needs
- to be a separate statement. */
- if (!is_gimple_reg (dst))
- {
- dtmp = make_rename_temp (TREE_TYPE (dst), "SR");
- stmt = gimple_build_assign (dtmp, var);
- gimple_seq_add_stmt (&seq, stmt);
- var = dtmp;
- }
- }
- stmt = gimple_build_assign (dst, var);
- gimple_seq_add_stmt (&seq, stmt);
+ push_gimplify_context (&gctx);
+ gctx.into_ssa = true;
+ gctx.allow_rhs_cond_expr = true;
+
+ gimplify_assign (dst, var, &seq);
+
+ if (gimple_referenced_vars (cfun))
+ for (var = gctx.temps; var; var = TREE_CHAIN (var))
+ add_referenced_var (var);
+ pop_gimplify_context (NULL);
return seq;
}