The following fixes redundant hard-register "stores" to be not eliminated by FRE/PRE and the alias machinery to properly handle different local VAR_DECLs with the same asm specification.
Comments are welcome. I tested the testcase on x86_64, ppc64le and aarch64 and all seem to be happy with *4 as register specification. Bootstrap / regtest running on x86_64-unknown-linux-gnu. Richard. 2017-04-25 Richard Biener <rguent...@suse.de> PR tree-optimization/80492 * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Do not eliminate redundant hardregister stores. * alias.c (compare_base_decls): Handle registers with asm specification conservatively. * tree-ssa-alias.c (decl_refs_may_alias_p): Handle compare_base_decls returning dont-know properly. * gcc.dg/pr80492.c: New testcase. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 247095) --- gcc/tree-ssa-pre.c (working copy) *************** eliminate_dom_walker::before_dom_childre *** 4495,4500 **** --- 4519,4526 ---- if (gimple_assign_single_p (stmt) && !gimple_has_volatile_ops (stmt) && !is_gimple_reg (gimple_assign_lhs (stmt)) + && !(TREE_CODE (gimple_assign_lhs (stmt)) == VAR_DECL + && DECL_HARD_REGISTER (gimple_assign_lhs (stmt))) && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME || is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))) { Index: gcc/alias.c =================================================================== *** gcc/alias.c (revision 247095) --- gcc/alias.c (working copy) *************** compare_base_decls (tree base1, tree bas *** 2046,2051 **** --- 2046,2063 ---- if (base1 == base2) return 1; + /* If we have two register decls with register specification we + cannot decide unless their assembler name is the same. */ + if (DECL_REGISTER (base1) + && DECL_REGISTER (base2) + && DECL_ASSEMBLER_NAME_SET_P (base1) + && DECL_ASSEMBLER_NAME_SET_P (base2)) + { + if (DECL_ASSEMBLER_NAME (base1) == DECL_ASSEMBLER_NAME (base2)) + return 1; + return -1; + } + /* Declarations of non-automatic variables may have aliases. All other decls are unique. */ if (!decl_in_symtab_p (base1) Index: gcc/tree-ssa-alias.c =================================================================== *** gcc/tree-ssa-alias.c (revision 247095) --- gcc/tree-ssa-alias.c (working copy) *************** decl_refs_may_alias_p (tree ref1, tree b *** 1096,1116 **** { gcc_checking_assert (DECL_P (base1) && DECL_P (base2)); /* If both references are based on different variables, they cannot alias. */ ! if (compare_base_decls (base1, base2) == 0) return false; /* If both references are based on the same variable, they cannot alias if the accesses do not overlap. */ ! if (!ranges_overlap_p (offset1, max_size1, offset2, max_size2)) ! return false; ! /* For components with variable position, the above test isn't sufficient, ! so we disambiguate component references manually. */ ! if (ref1 && ref2 ! && handled_component_p (ref1) && handled_component_p (ref2) ! && nonoverlapping_component_refs_of_decl_p (ref1, ref2)) ! return false; return true; } --- 1128,1153 ---- { gcc_checking_assert (DECL_P (base1) && DECL_P (base2)); + int cmp = compare_base_decls (base1, base2); + /* If both references are based on different variables, they cannot alias. */ ! if (cmp == 0) return false; /* If both references are based on the same variable, they cannot alias if the accesses do not overlap. */ ! if (cmp == 1) ! { ! if (!ranges_overlap_p (offset1, max_size1, offset2, max_size2)) ! return false; ! /* For components with variable position, the above test isn't sufficient, ! so we disambiguate component references manually. */ ! if (ref1 && ref2 ! && handled_component_p (ref1) && handled_component_p (ref2) ! && nonoverlapping_component_refs_of_decl_p (ref1, ref2)) ! return false; ! } return true; } Index: gcc/testsuite/gcc.dg/pr80492.c =================================================================== *** gcc/testsuite/gcc.dg/pr80492.c (nonexistent) --- gcc/testsuite/gcc.dg/pr80492.c (working copy) *************** *** 0 **** --- 1,20 ---- + /* { dg-do compile } */ + /* { dg-options "-w -O2 -fdump-tree-optimized" } */ + + static __inline__ __attribute__((__always_inline__)) + void syscall_7 (int val) + { + register int reg __asm ("4") = val; + __asm __volatile__ ("/* Some Code %0 */" :: "r" (reg)); + } + + void do_syscalls (void) + { + for (int s = 0; s < 2; s++) + { + syscall_7 (0); + syscall_7 (1); + } + } + + /* { dg-final { scan-tree-dump-times "reg = " 4 "optimized" } } */