This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, 4.5] Make fwprop find out that non-virtual constant member pointers are non-virtual
- From: Martin Jambor <mjambor at suse dot cz>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Guenther <rguenther at suse dot de>
- Date: Tue, 24 Mar 2009 19:37:01 +0100
- Subject: [PATCH, 4.5] Make fwprop find out that non-virtual constant member pointers are non-virtual
Hi,
this is a second attempt to partially fix PR 3713 - partial in the
sence that it does away with the rather embarrasing run-time
condition, for more details see the thread that started with the first
attempt:
http://gcc.gnu.org/ml/gcc-patches/2009-03/msg00536.html
The patch below takes the core of the fix to fold-const.c by partially
undoing the fix for PR 35705. I believe that this shouls still work
on any target on which member pointers work. I have not verified on a
hppa yet because gcc61 was down until recently. I will test it there
tomorrow. The hunks in tree-ssa-forwprop.c is not necessary (a tleast
not for the test case), FRE would manage to get rid of the condition
even without it. However, this way we get rid of it sooner (and hey,
once we might be able to do so in the early fwprop).
I have bootstrapped and tested this on x86_64-linux. Provided it does
not reintroduce PR 35705, is it OK for 4.5?
Thanks,
Martin
2009-03-24 Martin Jambor <mjambor@suse.cz>
* fold-const.c (get_pointer_modulus_and_residue): New parameter
allow_func_align.
(fold_binary): Allow function decl aligment consideration is the
second argument is integer constant one.
* tree-ssa-forwprop.c (simplify_bitwise_and): New function.
(tree_ssa_forward_propagate_single_use_vars): Handle assing statements
with BIT_AND_EXPR on the RHS by calling simplify_bitwise_and.
Index: iinln/gcc/tree-ssa-forwprop.c
===================================================================
--- iinln.orig/gcc/tree-ssa-forwprop.c
+++ iinln/gcc/tree-ssa-forwprop.c
@@ -147,6 +147,14 @@ along with GCC; see the file COPYING3.
ptr2 = &x[index];
+ Or
+ ssa = (int) decl
+ res = ssa & 1
+
+ Provided that decl has known alignment >= 2, will get turned into
+
+ res = 0
+
We also propagate casts into SWITCH_EXPR and COND_EXPR conditions to
allow us to remove the cast and {NOT_EXPR,NEG_EXPR} into a subsequent
{NOT_EXPR,NEG_EXPR}.
@@ -1124,6 +1132,42 @@ simplify_gimple_switch (gimple stmt)
}
}
+/* Run bitwise and assignments throug the folder. If the first argument is an
+ ssa name that is itself a result of a typecast of an ADDR_EXPR to an
+ integer, feed the ADDR_EXPR to the folder rather than the ssa name.
+*/
+
+static void
+simplify_bitwise_and (gimple_stmt_iterator *gsi, gimple stmt)
+{
+ tree res;
+ tree arg1 = gimple_assign_rhs1 (stmt);
+ tree arg2 = gimple_assign_rhs2 (stmt);
+
+ if (TREE_CODE (arg1) == SSA_NAME && !SSA_NAME_IS_DEFAULT_DEF (arg1))
+ {
+ gimple def = SSA_NAME_DEF_STMT (arg1);
+
+ if (gimple_assign_cast_p (def)
+ && INTEGRAL_TYPE_P (gimple_expr_type (def)))
+ {
+ tree op = gimple_assign_rhs1 (def);
+
+ if (TREE_CODE (op) == ADDR_EXPR)
+ arg1 = op;
+ }
+ }
+
+ res = fold_binary (BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)),
+ arg1, arg2);
+ if (res)
+ {
+ gimple_assign_set_rhs_from_tree (gsi, res);
+ update_stmt (stmt);
+ }
+ return;
+}
+
/* Main entry point for the forward propagation optimizer. */
static unsigned int
@@ -1206,6 +1250,11 @@ tree_ssa_forward_propagate_single_use_va
else
gsi_next (&gsi);
}
+ else if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR)
+ {
+ simplify_bitwise_and (&gsi, stmt);
+ gsi_next (&gsi);
+ }
else
gsi_next (&gsi);
}
Index: iinln/gcc/testsuite/g++.dg/tree-ssa/fwprop-align.C
===================================================================
--- /dev/null
+++ iinln/gcc/testsuite/g++.dg/tree-ssa/fwprop-align.C
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop2" } */
+
+struct A
+{
+ void foo ()
+ {
+ }
+};
+
+int main()
+{
+ void (A::* const p)() = & A::foo;
+ A a;
+ (a.*p)();
+}
+
+/* We should eliminate the check if p points to a virtual function. */
+/* { dg-final { scan-tree-dump-times "& 1" 0 "forwprop2" } } */
+/* { dg-final { cleanup-tree-dump "forwprop2" } } */
Index: iinln/gcc/fold-const.c
===================================================================
--- iinln.orig/gcc/fold-const.c
+++ iinln/gcc/fold-const.c
@@ -9590,10 +9590,15 @@ fold_mult_zconjz (tree type, tree expr)
0 <= N < M as is common. In general, the precise value of P is unknown.
M is chosen as large as possible such that constant N can be determined.
- Returns M and sets *RESIDUE to N. */
+ Returns M and sets *RESIDUE to N.
+
+ If ALLOW_FUNC_ALIGN is true, do take functions' DECL_ALIGN_UNIT into
+ account. This is not always possible due to PR 35705.
+ */
static unsigned HOST_WIDE_INT
-get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue)
+get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
+ bool allow_func_align)
{
enum tree_code code;
@@ -9623,7 +9628,8 @@ get_pointer_modulus_and_residue (tree ex
}
}
- if (DECL_P (expr) && TREE_CODE (expr) != FUNCTION_DECL)
+ if (DECL_P (expr)
+ && (allow_func_align || TREE_CODE (expr) != FUNCTION_DECL))
return DECL_ALIGN_UNIT (expr);
}
else if (code == POINTER_PLUS_EXPR)
@@ -9634,7 +9640,8 @@ get_pointer_modulus_and_residue (tree ex
op0 = TREE_OPERAND (expr, 0);
STRIP_NOPS (op0);
- modulus = get_pointer_modulus_and_residue (op0, residue);
+ modulus = get_pointer_modulus_and_residue (op0, residue,
+ allow_func_align);
op1 = TREE_OPERAND (expr, 1);
STRIP_NOPS (op1);
@@ -11274,7 +11281,8 @@ fold_binary (enum tree_code code, tree t
unsigned HOST_WIDE_INT modulus, residue;
unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (arg1);
- modulus = get_pointer_modulus_and_residue (arg0, &residue);
+ modulus = get_pointer_modulus_and_residue (arg0, &residue,
+ integer_onep (arg1));
/* This works because modulus is a power of 2. If this weren't the
case, we'd have to replace it by its greatest power-of-2