The following works around an issue in IPA SRA which does analysis twice, once on the original function body and once on the cloned one when replacing refs. If both end up not agreeing we end up with stale unreplaced refs - as in this case where earlier analysis had access to SSA range info which isn't copied in the process of cloning.
Thus the following patch copies over SSA range info which is a good idea anyways. Not sure to what extent the IPA SRA issue will prevail with the new implementation. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2019-06-26 Richard Biener <rguent...@suse.de> PR ipa/90982 * tree-inline.c (remap_ssa_name): Copy SSA range info. * g++.dg/torture/pr90982.C: New testcase. Index: gcc/tree-inline.c =================================================================== --- gcc/tree-inline.c (revision 272636) +++ gcc/tree-inline.c (working copy) @@ -259,6 +259,11 @@ remap_ssa_name (tree name, copy_body_dat struct ptr_info_def *new_pi = get_ptr_info (new_tree); new_pi->pt = pi->pt; } + /* So can range-info. */ + if (!POINTER_TYPE_P (TREE_TYPE (name)) + && SSA_NAME_RANGE_INFO (name)) + duplicate_ssa_name_range_info (new_tree, SSA_NAME_RANGE_TYPE (name), + SSA_NAME_RANGE_INFO (name)); return new_tree; } @@ -292,6 +297,11 @@ remap_ssa_name (tree name, copy_body_dat struct ptr_info_def *new_pi = get_ptr_info (new_tree); new_pi->pt = pi->pt; } + /* So can range-info. */ + if (!POINTER_TYPE_P (TREE_TYPE (name)) + && SSA_NAME_RANGE_INFO (name)) + duplicate_ssa_name_range_info (new_tree, SSA_NAME_RANGE_TYPE (name), + SSA_NAME_RANGE_INFO (name)); if (SSA_NAME_IS_DEFAULT_DEF (name)) { /* By inlining function having uninitialized variable, we might Index: gcc/testsuite/g++.dg/torture/pr90982.C =================================================================== --- gcc/testsuite/g++.dg/torture/pr90982.C (nonexistent) +++ gcc/testsuite/g++.dg/torture/pr90982.C (working copy) @@ -0,0 +1,23 @@ +// { dg-do compile } + +template <int n> struct S +{ + long c[n]; + void f (S d) + { + for (int i = 2;; i++) + c[i] &= d.c[i]; + } +}; + +template <int m> struct T:S<m/64> +{ + void operator &= (T d) + { this -> f (d); } +}; + +void g (T<192> &d) +{ + T<192> v; + d &= v; +}