On Tue, 10 May 2011, Richard Guenther wrote: > And I now get > > FAIL: gcc.target/i386/pr45903.c scan-assembler-not shr[qdl] > > because the optimization Jakub put in place relies on operations > carried out in smaller modes. > > That's of course a conflict of interest. I'm going to sit on this > patch for a little longer.
The following seems to work for all cases I am interested in. It avoids undoing narrowing optimizations if they were not to bitfield types. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2011-05-11 Richard Guenther <rguent...@suse.de> PR tree-optimization/18041 * tree-ssa-forwprop.c (simplify_bitwise_and): Rename to ... (simplify_bitwise_binary): ... this. Handle operand conversions by applying them to the result instead. (tree_ssa_forward_propagate_single_use_vars): Adjust. CSE tree code. * gcc.dg/tree-ssa/forwprop-13.c: New testcase. Index: gcc/tree-ssa-forwprop.c =================================================================== *** gcc/tree-ssa-forwprop.c.orig 2011-05-10 16:18:16.000000000 +0200 --- gcc/tree-ssa-forwprop.c 2011-05-10 17:50:43.000000000 +0200 *************** simplify_builtin_call (gimple_stmt_itera *** 1612,1655 **** return false; } ! /* 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 (arg2) != INTEGER_CST) ! return; ! ! 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_loc (gimple_location (stmt), ! BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)), ! arg1, arg2); ! if (res && is_gimple_min_invariant (res)) { ! gimple_assign_set_rhs_from_tree (gsi, res); ! update_stmt (stmt); } ! return; } --- 1612,1701 ---- return false; } ! /* Simplify bitwise binary operations. ! Return true if a transformation applied, otherwise return false. */ ! static bool ! simplify_bitwise_binary (gimple_stmt_iterator *gsi) { ! gimple stmt = gsi_stmt (*gsi); tree arg1 = gimple_assign_rhs1 (stmt); tree arg2 = gimple_assign_rhs2 (stmt); + enum tree_code code = gimple_assign_rhs_code (stmt); + tree res; ! /* 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. */ ! if (code == BIT_AND_EXPR ! && TREE_CODE (arg2) == INTEGER_CST ! && TREE_CODE (arg1) == SSA_NAME) { gimple def = SSA_NAME_DEF_STMT (arg1); + tree op = arg1; ! /* ??? This looks bogus - the conversion could be truncating. */ ! if (is_gimple_assign (def) ! && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)) ! && INTEGRAL_TYPE_P (TREE_TYPE (arg1))) ! { ! tree opp = gimple_assign_rhs1 (def); ! if (TREE_CODE (opp) == ADDR_EXPR) ! op = opp; ! } ! res = fold_binary_loc (gimple_location (stmt), ! BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)), ! op, arg2); ! if (res && is_gimple_min_invariant (res)) ! { ! gimple_assign_set_rhs_from_tree (gsi, res); ! update_stmt (stmt); ! return true; } } ! /* For bitwise binary operations apply operand conversions to the ! binary operation result instead of to the operands. This allows ! to combine successive conversions and bitwise binary operations. */ ! if (TREE_CODE (arg1) == SSA_NAME ! && TREE_CODE (arg2) == SSA_NAME) { ! gimple def_stmt1 = SSA_NAME_DEF_STMT (arg1); ! gimple def_stmt2 = SSA_NAME_DEF_STMT (arg2); ! if (is_gimple_assign (def_stmt1) ! && is_gimple_assign (def_stmt2) ! && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt1)) ! && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))) ! { ! tree darg1 = gimple_assign_rhs1 (def_stmt1); ! tree darg2 = gimple_assign_rhs1 (def_stmt2); ! /* Make sure that the conversion widens the operands or that it ! changes the operation to a bitfield precision. */ ! if (types_compatible_p (TREE_TYPE (darg1), TREE_TYPE (darg2)) ! && ((TYPE_PRECISION (TREE_TYPE (darg1)) ! < TYPE_PRECISION (TREE_TYPE (arg1))) ! || (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (arg1))) ! != MODE_INT) ! || (TYPE_PRECISION (TREE_TYPE (arg1)) ! != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (arg1)))))) ! { ! gimple newop; ! tree tem = create_tmp_reg (TREE_TYPE (darg1), ! NULL); ! newop = gimple_build_assign_with_ops (code, tem, darg1, darg2); ! tem = make_ssa_name (tem, newop); ! gimple_assign_set_lhs (newop, tem); ! gsi_insert_before (gsi, newop, GSI_SAME_STMT); ! gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR, ! tem, NULL_TREE, NULL_TREE); ! update_stmt (gsi_stmt (*gsi)); ! return true; ! } ! } } ! ! return false; } *************** tree_ssa_forward_propagate_single_use_va *** 2123,2128 **** --- 2169,2175 ---- { tree lhs = gimple_assign_lhs (stmt); tree rhs = gimple_assign_rhs1 (stmt); + enum tree_code code = gimple_assign_rhs_code (stmt); if (TREE_CODE (lhs) != SSA_NAME) { *************** tree_ssa_forward_propagate_single_use_va *** 2130,2139 **** continue; } ! if (gimple_assign_rhs_code (stmt) == ADDR_EXPR /* Handle pointer conversions on invariant addresses as well, as this is valid gimple. */ ! || (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt)) && TREE_CODE (rhs) == ADDR_EXPR && POINTER_TYPE_P (TREE_TYPE (lhs)))) { --- 2177,2186 ---- continue; } ! if (code == ADDR_EXPR /* Handle pointer conversions on invariant addresses as well, as this is valid gimple. */ ! || (CONVERT_EXPR_CODE_P (code) && TREE_CODE (rhs) == ADDR_EXPR && POINTER_TYPE_P (TREE_TYPE (lhs)))) { *************** tree_ssa_forward_propagate_single_use_va *** 2151,2157 **** else gsi_next (&gsi); } ! else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR && can_propagate_from (stmt)) { if (TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST --- 2198,2204 ---- else gsi_next (&gsi); } ! else if (code == POINTER_PLUS_EXPR && can_propagate_from (stmt)) { if (TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST *************** tree_ssa_forward_propagate_single_use_va *** 2183,2196 **** else gsi_next (&gsi); } ! else if ((gimple_assign_rhs_code (stmt) == BIT_NOT_EXPR ! || gimple_assign_rhs_code (stmt) == NEGATE_EXPR) && TREE_CODE (rhs) == SSA_NAME) { simplify_not_neg_expr (&gsi); gsi_next (&gsi); } ! else if (gimple_assign_rhs_code (stmt) == COND_EXPR) { /* In this case the entire COND_EXPR is in rhs1. */ int did_something; --- 2230,2243 ---- else gsi_next (&gsi); } ! else if ((code == BIT_NOT_EXPR ! || code == NEGATE_EXPR) && TREE_CODE (rhs) == SSA_NAME) { simplify_not_neg_expr (&gsi); gsi_next (&gsi); } ! else if (code == COND_EXPR) { /* In this case the entire COND_EXPR is in rhs1. */ int did_something; *************** tree_ssa_forward_propagate_single_use_va *** 2203,2229 **** && did_something, stmt, WARN_STRICT_OVERFLOW_CONDITIONAL); gsi_next (&gsi); } ! else if (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) ! == tcc_comparison) { if (forward_propagate_comparison (stmt)) cfg_changed = true; gsi_next (&gsi); } ! else if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR) { ! simplify_bitwise_and (&gsi, stmt); ! gsi_next (&gsi); } ! else if (gimple_assign_rhs_code (stmt) == PLUS_EXPR ! || gimple_assign_rhs_code (stmt) == MINUS_EXPR) { cfg_changed |= associate_plusminus (stmt); gsi_next (&gsi); } ! else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt)) ! || gimple_assign_rhs_code (stmt) == FLOAT_EXPR ! || gimple_assign_rhs_code (stmt) == FIX_TRUNC_EXPR) { if (!combine_conversions (&gsi)) gsi_next (&gsi); --- 2250,2277 ---- && did_something, stmt, WARN_STRICT_OVERFLOW_CONDITIONAL); gsi_next (&gsi); } ! else if (TREE_CODE_CLASS (code) == tcc_comparison) { if (forward_propagate_comparison (stmt)) cfg_changed = true; gsi_next (&gsi); } ! else if (code == BIT_AND_EXPR ! || code == BIT_IOR_EXPR ! || code == BIT_XOR_EXPR) { ! if (!simplify_bitwise_binary (&gsi)) ! gsi_next (&gsi); } ! else if (code == PLUS_EXPR ! || code == MINUS_EXPR) { cfg_changed |= associate_plusminus (stmt); gsi_next (&gsi); } ! else if (CONVERT_EXPR_CODE_P (code) ! || code == FLOAT_EXPR ! || code == FIX_TRUNC_EXPR) { if (!combine_conversions (&gsi)) gsi_next (&gsi); Index: gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c 2011-05-10 17:42:33.000000000 +0200 *************** *** 0 **** --- 1,16 ---- + /* { dg-do compile } */ + /* { dg-options "-O -fdump-tree-optimized" } */ + + struct B { + unsigned bit0 : 1; + unsigned bit1 : 1; + }; + + void + foo (struct B *b) + { + b->bit0 = b->bit0 | b->bit1; + } + + /* { dg-final { scan-tree-dump-not "\\\(unsigned" "optimized" } } */ + /* { dg-final { cleanup-tree-dump "optimized" } } */