https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101454
Bug ID: 101454 Summary: debug info for unreachable var forces another var to be output Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: debug Assignee: unassigned at gcc dot gnu.org Reporter: aoliva at gcc dot gnu.org Target Milestone: --- If some IPA pass replaces the only reference to a constant non-public non-automatic variable with its initializer, namely the address of another such variable, the former becomes unreferenced and it's discarded by symbol_table::remove_unreachable_nodes. It calls debug_hooks->late_global_decl while at that, and this expands the initializer, which assigs RTL to the latter variable and forces it to be retained by remove_unreferenced_decls, and eventually be output despite not being referenced. Without debug information, it's not output. This has caused a bootstrap-debug compare failure in libdecnumber/decContext.o, while developing a transformation that ends up enabling the above substitution in constprop. I've proposed a patch that makes reference_to_unused slightly more conservative about such variables at the end of IPA passes, falling back onto expand_debug_expr for expressions referencing symbols that might or might not be output, avoiding the loss of debug information when the symbol is output, while avoiding a symbol output only because of debug info. https://gcc.gnu.org/pipermail/gcc-patches/2021-July/575043.html richi suggested using symbolic DIE references, later resolved by note_variable_values. Maybe we do this unconditionally for the initializers of removed decls. That seems doable and desirable. decContext.c doesn't generate location or const_value for neither mfctop nor mfcone, even after removing rtl_for_decl_location from add_location_or_const_value_attribute, despite lookup_decl_loc's finding a location expression. Alas, I haven't managed to come up with a testcase to trigger the problem without the patchset that I'm not yet ready to contribute. https://gcc.gnu.org/pipermail/gcc/2021-July/236780.html The kicker, in case someone wants to force it, is that at materialize_all_clones, the reference to mfctop in a constprop-ed decContextTestEndian gets substituted by its constant initializer, &mfcone, so mfctop becomes unreachable and goes through late_global_decl in remove_unreachable_nodes. Eventually, ccp2 resolves the mfcone dereference to a constant, and no reason remains for mfcone to be output. However, when outputting debug info, the expand_expr of mfctop's initializer will have already generated RTL for mfcone, committing it to be output, wehreas without debug info, mfcone is not output at all. What enables these transformations during IPA is the introduction of a wrapper for decContextTestEndian, moving its body to a clone that is materialized early, at the end of all_small_ipa_passes. This clone, being a local function, seems to be what enables the substitution of the mfctop constant initializer. I haven't found a way to cause such a difference without my pass, even getting a constprop (local) clone for the function, and preventing its inlining into an exported function. Hopefully this is enough information to enable the issue to be investigated.