[backport from gcc-4.7/trunk ] gcc/ 2011-12-22 Bin Cheng Richard Guenther PR tree-optimization/43491 * tree-ssa-pre.c (eliminate): Don't replace global register variable when it is the RHS of a single assign. gcc/testsuite/ 2011-12-22 Bin Cheng PR tree-optimization/43491 * gcc.dg/tree-ssa/pr43491.c: New test. --- gcc-4.6.2/gcc/testsuite/gcc.dg/tree-ssa/pr43491.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.6.2/gcc/testsuite/gcc.dg/tree-ssa/pr43491.c 2011-12-23 16:03:42.000000000 +0100 @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +#define REGISTER register + +#if defined __arm__ +# define REG1 asm("r4") +#elif defined __i386__ +# define REG1 asm("ebx") +#elif defined __mips__ +# define REG1 asm("s0") +#elif defined __x86_64__ +# define REG1 asm("rbp") +#else +# undef REGISTER +# define REGISTER +# define REG1 +#endif + +REGISTER long data_0 REG1; +long data_3; + +long foo(long data, long v) +{ + long i; + long t, u; + + if (data) + i = data_0 + data_3; + else { + v = 2; + i = 5; + } + t = data_0 + data_3; + u = i; + return v * t * u; +} +/* We should not eliminate global register variable when it is the RHS of + a single assignment. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre" { target { arm-*-* i?86-*-* mips*-*-* x86_64-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Eliminated: 3" 1 "pre" { target { ! { arm-*-* i?86-*-* mips*-*-* x86_64-*-* } } } } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ --- gcc-4.6.2/gcc/tree-ssa-pre.c.~1~ 2011-07-16 13:33:28.000000000 +0200 +++ gcc-4.6.2/gcc/tree-ssa-pre.c 2011-12-23 16:03:42.000000000 +0100 @@ -4195,28 +4195,40 @@ eliminate (void) { for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi)) { + tree lhs = NULL_TREE; + tree rhs = NULL_TREE; + stmt = gsi_stmt (gsi); + if (gimple_has_lhs (stmt)) + lhs = gimple_get_lhs (stmt); + + if (gimple_assign_single_p (stmt)) + rhs = gimple_assign_rhs1 (stmt); + /* Lookup the RHS of the expression, see if we have an available computation for it. If so, replace the RHS with - the available computation. */ + the available computation. + + See PR43491. + We don't replace global register variable when it is a the RHS of + a single assign. We do replace local register variable since gcc + does not guarantee local variable will be allocated in register. */ if (gimple_has_lhs (stmt) - && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME + && TREE_CODE (lhs) == SSA_NAME && !gimple_assign_ssa_name_copy_p (stmt) && (!gimple_assign_single_p (stmt) - || !is_gimple_min_invariant (gimple_assign_rhs1 (stmt))) + || (!is_gimple_min_invariant (rhs) + && (gimple_assign_rhs_code (stmt) != VAR_DECL + || !is_global_var (rhs) + || !DECL_HARD_REGISTER (rhs)))) && !gimple_has_volatile_ops (stmt) - && !has_zero_uses (gimple_get_lhs (stmt))) + && !has_zero_uses (lhs)) { - tree lhs = gimple_get_lhs (stmt); - tree rhs = NULL_TREE; tree sprime = NULL; pre_expr lhsexpr = get_or_alloc_expr_for_name (lhs); pre_expr sprimeexpr; - if (gimple_assign_single_p (stmt)) - rhs = gimple_assign_rhs1 (stmt); - sprimeexpr = bitmap_find_leader (AVAIL_OUT (b), get_expr_value_id (lhsexpr), NULL); @@ -4332,10 +4344,9 @@ eliminate (void) dead. */ else if (gimple_assign_single_p (stmt) && !is_gimple_reg (gimple_assign_lhs (stmt)) - && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME - || is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))) + && (TREE_CODE (rhs) == SSA_NAME + || is_gimple_min_invariant (rhs))) { - tree rhs = gimple_assign_rhs1 (stmt); tree val; val = vn_reference_lookup (gimple_assign_lhs (stmt), gimple_vuse (stmt), VN_WALK, NULL);