This prepares things to share constant folding between passes (CCP, FRE and VRP). It simplifies maybe_fold_reference making sure to first canonicalize MEM_REFs and then call other folders.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2011-03-16 Richard Guenther <rguent...@suse.de> * gimple-fold.c (maybe_fold_reference): Open-code relevant constant folding. Move MEM_REF canonicalization first. Rely on fold_const_aggregate_ref for initializer folding. * tree-ssa-ccp.c (ccp_fold): Handle constant vector extracts. * gcc.dg/tree-ssa/pr14814.c: Adjust. * gcc.dg/tree-ssa/ssa-ccp-19.c: Likewise. Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c.orig 2011-03-16 10:53:10.000000000 +0100 --- gcc/gimple-fold.c 2011-03-16 11:20:40.000000000 +0100 *************** maybe_fold_reference (tree expr, bool is *** 560,582 **** tree *t = &expr; tree result; ! if (!is_lhs ! && (result = fold_const_aggregate_ref (expr)) ! && is_gimple_min_invariant (result)) ! return result; ! /* ??? We might want to open-code the relevant remaining cases ! to avoid using the generic fold. */ ! if (handled_component_p (*t) ! && CONSTANT_CLASS_P (TREE_OPERAND (*t, 0))) { ! tree tem = fold (*t); ! if (tem != *t) ! return tem; } ! while (handled_component_p (*t)) ! t = &TREE_OPERAND (*t, 0); /* Fold back MEM_REFs to reference trees. */ if (TREE_CODE (*t) == MEM_REF --- 560,609 ---- tree *t = &expr; tree result; ! if ((TREE_CODE (expr) == VIEW_CONVERT_EXPR ! || TREE_CODE (expr) == REALPART_EXPR ! || TREE_CODE (expr) == IMAGPART_EXPR) ! && CONSTANT_CLASS_P (TREE_OPERAND (expr, 0))) ! return fold_unary_loc (EXPR_LOCATION (expr), ! TREE_CODE (expr), ! TREE_TYPE (expr), ! TREE_OPERAND (expr, 0)); ! else if (TREE_CODE (expr) == BIT_FIELD_REF ! && CONSTANT_CLASS_P (TREE_OPERAND (expr, 0))) ! return fold_ternary_loc (EXPR_LOCATION (expr), ! TREE_CODE (expr), ! TREE_TYPE (expr), ! TREE_OPERAND (expr, 0), ! TREE_OPERAND (expr, 1), ! TREE_OPERAND (expr, 2)); ! ! while (handled_component_p (*t)) ! t = &TREE_OPERAND (*t, 0); ! /* Canonicalize MEM_REFs invariant address operand. Do this first ! to avoid feeding non-canonical MEM_REFs elsewhere. */ ! if (TREE_CODE (*t) == MEM_REF ! && !is_gimple_mem_ref_addr (TREE_OPERAND (*t, 0))) { ! bool volatile_p = TREE_THIS_VOLATILE (*t); ! tree tem = fold_binary (MEM_REF, TREE_TYPE (*t), ! TREE_OPERAND (*t, 0), ! TREE_OPERAND (*t, 1)); ! if (tem) ! { ! TREE_THIS_VOLATILE (tem) = volatile_p; ! *t = tem; ! tem = maybe_fold_reference (expr, is_lhs); ! if (tem) ! return tem; ! return expr; ! } } ! if (!is_lhs ! && (result = fold_const_aggregate_ref (expr)) ! && is_gimple_min_invariant (result)) ! return result; /* Fold back MEM_REFs to reference trees. */ if (TREE_CODE (*t) == MEM_REF *************** maybe_fold_reference (tree expr, bool is *** 593,599 **** compatibility. */ && types_compatible_p (TREE_TYPE (*t), TREE_TYPE (TREE_OPERAND ! (TREE_OPERAND (*t, 0), 0)))) { tree tem; *t = TREE_OPERAND (TREE_OPERAND (*t, 0), 0); --- 620,626 ---- compatibility. */ && types_compatible_p (TREE_TYPE (*t), TREE_TYPE (TREE_OPERAND ! (TREE_OPERAND (*t, 0), 0)))) { tree tem; *t = TREE_OPERAND (TREE_OPERAND (*t, 0), 0); *************** maybe_fold_reference (tree expr, bool is *** 602,625 **** return tem; return expr; } - /* Canonicalize MEM_REFs invariant address operand. */ - else if (TREE_CODE (*t) == MEM_REF - && !is_gimple_mem_ref_addr (TREE_OPERAND (*t, 0))) - { - bool volatile_p = TREE_THIS_VOLATILE (*t); - tree tem = fold_binary (MEM_REF, TREE_TYPE (*t), - TREE_OPERAND (*t, 0), - TREE_OPERAND (*t, 1)); - if (tem) - { - TREE_THIS_VOLATILE (tem) = volatile_p; - *t = tem; - tem = maybe_fold_reference (expr, is_lhs); - if (tem) - return tem; - return expr; - } - } else if (TREE_CODE (*t) == TARGET_MEM_REF) { tree tem = maybe_fold_tmr (*t); --- 629,634 ---- *************** maybe_fold_reference (tree expr, bool is *** 629,648 **** tem = maybe_fold_reference (expr, is_lhs); if (tem) return tem; - return expr; - } - } - else if (!is_lhs - && DECL_P (*t)) - { - tree tem = get_symbol_constant_value (*t); - if (tem - && useless_type_conversion_p (TREE_TYPE (*t), TREE_TYPE (tem))) - { - *t = unshare_expr (tem); - tem = maybe_fold_reference (expr, is_lhs); - if (tem) - return tem; return expr; } } --- 638,643 ---- Index: gcc/testsuite/gcc.dg/tree-ssa/pr14814.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/pr14814.c.orig 2011-03-16 10:53:21.000000000 +0100 --- gcc/testsuite/gcc.dg/tree-ssa/pr14814.c 2011-03-16 11:04:42.000000000 +0100 *************** int foo(const struct XX* r) { *** 18,22 **** return 1; } ! /* { dg-final { scan-tree-dump-times "&" 0 "forwprop2" } } */ /* { dg-final { cleanup-tree-dump "forwprop2" } } */ --- 18,22 ---- return 1; } ! /* { dg-final { scan-tree-dump-times "= &" 0 "forwprop2" } } */ /* { dg-final { cleanup-tree-dump "forwprop2" } } */ Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-19.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-19.c.orig 2011-03-16 10:53:21.000000000 +0100 --- gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-19.c 2011-03-16 11:02:47.000000000 +0100 *************** int g() *** 12,16 **** return *i; /* This should be turned into a.i */ } ! /* { dg-final { scan-tree-dump "= a.i;" "ccp1" } } */ /* { dg-final { cleanup-tree-dump "ccp1" } } */ --- 12,16 ---- return *i; /* This should be turned into a.i */ } ! /* { dg-final { scan-tree-dump "= MEM\\\[\\\(int \\\*\\\)&a\\\];" "ccp1" } } */ /* { dg-final { cleanup-tree-dump "ccp1" } } */ Index: gcc/tree-ssa-ccp.c =================================================================== *** gcc/tree-ssa-ccp.c.orig 2011-03-16 10:53:21.000000000 +0100 --- gcc/tree-ssa-ccp.c 2011-03-16 10:56:36.000000000 +0100 *************** ccp_fold (gimple stmt) *** 1182,1187 **** --- 1182,1198 ---- TREE_CODE (rhs), TREE_TYPE (rhs), val); } + else if (TREE_CODE (rhs) == BIT_FIELD_REF + && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME) + { + tree val = get_constant_value (TREE_OPERAND (rhs, 0)); + if (val) + return fold_ternary_loc (EXPR_LOCATION (rhs), + TREE_CODE (rhs), + TREE_TYPE (rhs), val, + TREE_OPERAND (rhs, 1), + TREE_OPERAND (rhs, 2)); + } else if (TREE_CODE (rhs) == MEM_REF && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME) {