This fixes the fallout of executing forwprop after FRE which runs before stdarg. forwprop transforms series of pointer increments to pointer increments of larger offset and uses &MEM[ptr + CST] as canonical form for ptr + CST (the former is is_gimple_min_invariant).
Bootstrapped and tested on x86_64-unknown-linux-gnu together with early FRE. Now re-bootstrapping and testing w/o that. I'm planning to commit this after that testing finished. Thanks, Richard. 2011-03-23 Richard Guenther <rguent...@suse.de> * tree-stdarg.c (va_list_counter_bump): Handle bumps via MEM_REF. (check_va_list_escapes): Likewise. (check_all_va_list_escapes): Likewise. Index: gcc/tree-stdarg.c =================================================================== *** gcc/tree-stdarg.c (revision 171340) --- gcc/tree-stdarg.c (working copy) *************** va_list_counter_bump (struct stdarg_info *** 133,138 **** --- 133,139 ---- while (lhs) { enum tree_code rhs_code; + tree rhs1; if (si->offsets[SSA_NAME_VERSION (lhs)] != -1) { *************** va_list_counter_bump (struct stdarg_info *** 152,172 **** return (unsigned HOST_WIDE_INT) -1; rhs_code = gimple_assign_rhs_code (stmt); if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS || gimple_assign_cast_p (stmt)) ! && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME) { ! lhs = gimple_assign_rhs1 (stmt); continue; } if ((rhs_code == POINTER_PLUS_EXPR || rhs_code == PLUS_EXPR) ! && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME && host_integerp (gimple_assign_rhs2 (stmt), 1)) { ret += tree_low_cst (gimple_assign_rhs2 (stmt), 1); ! lhs = gimple_assign_rhs1 (stmt); continue; } --- 153,184 ---- return (unsigned HOST_WIDE_INT) -1; rhs_code = gimple_assign_rhs_code (stmt); + rhs1 = gimple_assign_rhs1 (stmt); if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS || gimple_assign_cast_p (stmt)) ! && TREE_CODE (rhs1) == SSA_NAME) { ! lhs = rhs1; continue; } if ((rhs_code == POINTER_PLUS_EXPR || rhs_code == PLUS_EXPR) ! && TREE_CODE (rhs1) == SSA_NAME && host_integerp (gimple_assign_rhs2 (stmt), 1)) { ret += tree_low_cst (gimple_assign_rhs2 (stmt), 1); ! lhs = rhs1; ! continue; ! } ! ! if (rhs_code == ADDR_EXPR ! && TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF ! && TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0)) == SSA_NAME ! && host_integerp (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1)) ! { ! ret += tree_low_cst (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1); ! lhs = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0); continue; } *************** va_list_counter_bump (struct stdarg_info *** 195,200 **** --- 207,213 ---- while (lhs) { enum tree_code rhs_code; + tree rhs1; if (si->offsets[SSA_NAME_VERSION (lhs)] != -1) break; *************** va_list_counter_bump (struct stdarg_info *** 207,227 **** stmt = SSA_NAME_DEF_STMT (lhs); rhs_code = gimple_assign_rhs_code (stmt); if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS || gimple_assign_cast_p (stmt)) ! && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME) { ! lhs = gimple_assign_rhs1 (stmt); continue; } if ((rhs_code == POINTER_PLUS_EXPR || rhs_code == PLUS_EXPR) ! && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME && host_integerp (gimple_assign_rhs2 (stmt), 1)) { val -= tree_low_cst (gimple_assign_rhs2 (stmt), 1); ! lhs = gimple_assign_rhs1 (stmt); continue; } --- 220,251 ---- stmt = SSA_NAME_DEF_STMT (lhs); rhs_code = gimple_assign_rhs_code (stmt); + rhs1 = gimple_assign_rhs1 (stmt); if ((get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS || gimple_assign_cast_p (stmt)) ! && TREE_CODE (rhs1) == SSA_NAME) { ! lhs = rhs1; continue; } if ((rhs_code == POINTER_PLUS_EXPR || rhs_code == PLUS_EXPR) ! && TREE_CODE (rhs1) == SSA_NAME && host_integerp (gimple_assign_rhs2 (stmt), 1)) { val -= tree_low_cst (gimple_assign_rhs2 (stmt), 1); ! lhs = rhs1; ! continue; ! } ! ! if (rhs_code == ADDR_EXPR ! && TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF ! && TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0)) == SSA_NAME ! && host_integerp (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1)) ! { ! val -= tree_low_cst (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1); ! lhs = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0); continue; } *************** check_va_list_escapes (struct stdarg_inf *** 433,441 **** if (! POINTER_TYPE_P (TREE_TYPE (rhs))) return; ! if (TREE_CODE (rhs) != SSA_NAME ! || ! bitmap_bit_p (si->va_list_escape_vars, ! DECL_UID (SSA_NAME_VAR (rhs)))) return; if (TREE_CODE (lhs) != SSA_NAME || is_global_var (SSA_NAME_VAR (lhs))) --- 457,478 ---- if (! POINTER_TYPE_P (TREE_TYPE (rhs))) return; ! if (TREE_CODE (rhs) == SSA_NAME) ! { ! if (! bitmap_bit_p (si->va_list_escape_vars, ! DECL_UID (SSA_NAME_VAR (rhs)))) ! return; ! } ! else if (TREE_CODE (rhs) == ADDR_EXPR ! && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF ! && TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0)) == SSA_NAME) ! { ! if (! bitmap_bit_p (si->va_list_escape_vars, ! DECL_UID (SSA_NAME_VAR (TREE_OPERAND ! (TREE_OPERAND (rhs, 0), 0))))) ! return; ! } ! else return; if (TREE_CODE (lhs) != SSA_NAME || is_global_var (SSA_NAME_VAR (lhs))) *************** check_all_va_list_escapes (struct stdarg *** 512,518 **** enum tree_code rhs_code = gimple_assign_rhs_code (stmt); /* x = *ap_temp; */ ! if (gimple_assign_rhs_code (stmt) == MEM_REF && TREE_OPERAND (rhs, 0) == use && TYPE_SIZE_UNIT (TREE_TYPE (rhs)) && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), 1) --- 549,555 ---- enum tree_code rhs_code = gimple_assign_rhs_code (stmt); /* x = *ap_temp; */ ! if (rhs_code == MEM_REF && TREE_OPERAND (rhs, 0) == use && TYPE_SIZE_UNIT (TREE_TYPE (rhs)) && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), 1) *************** check_all_va_list_escapes (struct stdarg *** 557,562 **** --- 594,609 ---- DECL_UID (lhs))) continue; } + else if (rhs_code == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF + && TREE_OPERAND (TREE_OPERAND (rhs, 0), 0) == use) + { + tree lhs = gimple_assign_lhs (stmt); + + if (bitmap_bit_p (si->va_list_escape_vars, + DECL_UID (SSA_NAME_VAR (lhs)))) + continue; + } } if (dump_file && (dump_flags & TDF_DETAILS))