> > I wonder why we bother producing summaries for things that do not > bind locally? The summary->kills.length () has an upper bound?
Because of local aliases. The size of the array is capped by param_max_modref_accesses which is 16. > > > + && summary->kills.length ()) > > + { > > + tree base = ao_ref_base (ref); > > + for (unsigned int i = 0; i < summary->kills.length (); i++) > > + { > > + modref_access_node &a = summary->kills[i]; > > + tree op; > > + poly_offset_int off1_adj = 0, off2_adj = 0; > > + poly_int64 off1, off2; > > + tree base_ptr = NULL; > > + tree base_decl = NULL; > > + > > + if (a.parm_index >= 0) > > + op = gimple_call_arg (stmt, a.parm_index); > > + else if (a.parm_index == MODREF_STATIC_CHAIN_PARM) > > + op = gimple_call_chain (stmt); > > + else > > + gcc_unreachable (); > > I wonder if we can abstract this to a modref_access_node method? Something like get_param (stmt)? Yes, it looks like a good idea. > > > + > > + off2_adj += a.parm_offset * BITS_PER_UNIT; > > wasn't there a parm_offset unknown? ... Yes, but we do not insert those accesses to kills since they are unknown. > > > + if (!(off2_adj + a.offset).to_shwi (&off2)) > > + continue; > > + if (TREE_CODE (base) == MEM_REF) > > + { > > + off1_adj = mem_ref_offset (base) << LOG2_BITS_PER_UNIT; > > + if (TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR) > > + base_decl = TREE_OPERAND (TREE_OPERAND (base, 0), 0); > > 'base' will be the decl in this case, apart from when the constant > offset doesn't fit ao_ref.offset, so I think you can spare this > special-case and give up on non-SSA base_ptr I tought we wrap decls to modrefs in lto streaming when type merging fails? > > > + else > > + base_ptr = TREE_OPERAND (base, 0); > > + } > > + /* Give up on TMRs for now. */ > > + else if (TREE_CODE (base) == TARGET_MEM_REF) > > + break; > > + else > > + base_decl = base; > > + > > + gcc_checking_assert (!base_decl || DECL_P (base_decl)); > > + gcc_checking_assert (!base_ptr > > + || TREE_CODE (base_ptr) == SSA_NAME); > > + > > + /* OP is a pointer and we have access range from its > > + dereference. */ > > + if (TREE_CODE (op) == ADDR_EXPR) > > + { > > + poly_int64 size, offset, max_size; > > + bool reverse; > > + tree op_base = get_ref_base_and_extent > > + (TREE_OPERAND (op, 0), &offset, &size, > > + &max_size, &reverse); > > I think you want get_addr_base_and_unit_offset here. All > variable indexed addresses are in separate stmts. That also means > you can eventually work with just byte sizes/offsets? Will do. The access range in modref summary is bit based (since we want to disabiguate bitfields like we do in rest of alias oracle) but indeed this part cna be in bytes. > > > + if (!known_size_p (size) || !known_eq (size, max_size)) > > + continue; > > + off2_adj += offset; > > + /* &str->foo are not passed as gimple operands directly, > > + would need to look up the def stmt. */ > > + gcc_checking_assert (TREE_CODE (op_base) != MEM_REF); > > + if (!base_decl > > + || compare_base_decls (op_base, base_decl) != 1) > > + continue; > > + } > > + else if (!base_ptr || !operand_equal_p (base_ptr, op)) > > + continue; > > + > > + if (!(off1_adj + ref->offset).to_shwi (&off1)) > > + continue; > > + if (!(off2_adj + a.offset).to_shwi (&off2)) > > + continue; > > + > > + if (known_subrange_p (off1, ref->max_size, off2, a.size) > > + && dbg_cnt (ipa_mod_ref)) > > + { > > + /* For store to be killed it needs to not be used earlier. */ > > + if (ref_maybe_used_by_call_p_1 (as_a <gcall *> (stmt), ref, > > + true)) > > Hmm, so moderf says p->x is killed when we have > > foo (struct X *p) > { > int tem = p->x; > p->x = 0; > return tem; > } > > ? Or even Yep, this will currently land in kills. I can add loop pruning kills with known load ranges incrementally. > > foo (struct X *p) > { > bar (); > p->x = 0; > } > > ? Here we will end up with reading global memory and that will turn kills empty in modref. The check is still needed to verify that ref is not passed as aggregate parameter. I will update patch. Thanks, Honza > > Otherwise it looks sensible. > > Richard.