https://gcc.gnu.org/g:414ce41976ae9ffe0349be181ae333e1616ece1c
commit 414ce41976ae9ffe0349be181ae333e1616ece1c Author: Ondřej Machota <ondrejmach...@gmail.com> Date: Tue Jun 24 09:54:54 2025 +0200 rtl-ssa-web: init pass, rtl-ssa accesses support uid Diff: --- gcc/passes.def | 1 + gcc/rtl-ssa/accesses.h | 17 ++++++- gcc/rtl-ssa/internals.inl | 4 ++ gcc/rtlanal.cc | 4 +- gcc/rtlanal.h | 16 ++++-- gcc/tree-pass.h | 1 + gcc/web.cc | 122 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 159 insertions(+), 6 deletions(-) diff --git a/gcc/passes.def b/gcc/passes.def index 3b251052e53a..777f1dc7e075 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -482,6 +482,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_rtl_loop_done); POP_INSERT_PASSES () NEXT_PASS (pass_lower_subreg2); + NEXT_PASS (pass_web_ssa); NEXT_PASS (pass_web); NEXT_PASS (pass_rtl_cprop); NEXT_PASS (pass_cse2); diff --git a/gcc/rtl-ssa/accesses.h b/gcc/rtl-ssa/accesses.h index 98403f78b37b..318fde10ee05 100644 --- a/gcc/rtl-ssa/accesses.h +++ b/gcc/rtl-ssa/accesses.h @@ -19,6 +19,8 @@ namespace rtl_ssa { +#include "coretypes.h" + // Forward declarations. class bb_info; class clobber_group; @@ -131,6 +133,8 @@ public: // otherwise return MEM_REGNO. unsigned int regno () const { return m_regno; } + const_rtx reg () const { return m_reg; } + // For sets, return the mode of the value to which the resource is being set. // For uses, return the mode in which the resource is being used (which for // hard registers might be different from the mode in which the resource @@ -208,6 +212,11 @@ public: // an insn that is about to be inserted. bool is_temporary () const { return m_is_temp; } + // User definable uid for use_info + unsigned int& uid () { return m_uid; } + + unsigned int uid () const { return m_uid; } + protected: access_info (resource_info, access_kind); @@ -246,6 +255,12 @@ protected: // a phi node. unsigned int m_is_in_debug_insn_or_phi : 1; + // Not null if is_reg is true. In that case it points to the reg. + const_rtx m_reg; + + // The value of uid (). + unsigned int m_uid; + private: // Used as a flag during various update routines; has no long-lasting // meaning. @@ -285,7 +300,7 @@ public: // resource's value. class use_info : public access_info { - // Overall size: 5 LP64 words. + // Overall size: 6 LP64 words. friend class set_info; friend class function_info; diff --git a/gcc/rtl-ssa/internals.inl b/gcc/rtl-ssa/internals.inl index 0de18bbefe67..b4b3e2da6b4a 100644 --- a/gcc/rtl-ssa/internals.inl +++ b/gcc/rtl-ssa/internals.inl @@ -95,6 +95,8 @@ use_info::record_reference (rtx_obj_reference ref, bool is_first) m_includes_multiregs |= ref.is_multireg (); m_only_occurs_in_notes &= ref.in_note (); } + + m_reg = ref.reg (); } // Change the value of insn () to INSN. @@ -208,6 +210,8 @@ def_info::record_reference (rtx_obj_reference ref, bool is_first) m_includes_subregs |= ref.in_subreg (); m_includes_multiregs |= ref.is_multireg (); } + + m_reg = ref.reg (); } // Return the last definition in the list. Only valid when is_first () diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc index 86a5e4733088..3963fd14ce5e 100644 --- a/gcc/rtlanal.cc +++ b/gcc/rtlanal.cc @@ -2102,7 +2102,7 @@ rtx_properties::try_to_add_reg (const_rtx x, unsigned int flags) for (unsigned int regno = start_regno; regno < end_regno; ++regno) if (ref_iter != ref_end) *ref_iter++ = rtx_obj_reference (regno, flags, mode, - regno - start_regno); + regno - start_regno, x); } /* Add a description of destination X to this object. FLAGS is a bitmask @@ -2169,7 +2169,7 @@ rtx_properties::try_to_add_dest (const_rtx x, unsigned int flags) anti-dependent on later deallocations, so both types of stack operation are akin to a memory write. */ if (ref_iter != ref_end) - *ref_iter++ = rtx_obj_reference (MEM_REGNO, flags, BLKmode); + *ref_iter++ = rtx_obj_reference (MEM_REGNO, flags, BLKmode, 0, x); /* We want to keep sp alive everywhere - by making all writes to sp also use sp. */ diff --git a/gcc/rtlanal.h b/gcc/rtlanal.h index 33f171624c92..3c4c1747891c 100644 --- a/gcc/rtlanal.h +++ b/gcc/rtlanal.h @@ -23,6 +23,9 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_RTLANAL_H #define GCC_RTLANAL_H +#include "coretypes.h" +#include "rtl.h" + /* A dummy register value that represents the whole of variable memory. Using ~0U means that arrays that track both registers and memory can be indexed by regno + 1. */ @@ -53,11 +56,14 @@ class rtx_obj_reference public: rtx_obj_reference () = default; rtx_obj_reference (unsigned int regno, uint16_t flags, - machine_mode mode, unsigned int multireg_offset = 0); + machine_mode mode, unsigned int multireg_offset = 0, + const_rtx reg = nullptr); bool is_reg () const { return regno != MEM_REGNO; } bool is_mem () const { return regno == MEM_REGNO; } + const_rtx reg () const { return m_reg; } + /* True if the reference is a read or a write respectively. Both flags are set in a read-modify-write context, such as for read_modify_subreg_p. */ @@ -95,6 +101,9 @@ public: /* The referenced register, or MEM_REGNO for variable memory. */ unsigned int regno; + /* The referenced the register, subregister or memory */ + const_rtx m_reg; + /* A bitmask of rtx_obj_flags. */ unsigned int flags : 16; @@ -109,9 +118,10 @@ public: /* Construct a reference with the given fields. */ inline rtx_obj_reference::rtx_obj_reference (unsigned int regno, uint16_t flags, - machine_mode mode, - unsigned int multireg_offset) + machine_mode mode, unsigned int multireg_offset, + const_rtx reg) : regno (regno), + m_reg (reg), flags (flags), mode (mode), multireg_offset (multireg_offset) diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 7cb5a128899a..36a8d4aaa8e1 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -592,6 +592,7 @@ extern rtl_opt_pass *make_pass_rtl_doloop (gcc::context *ctxt); extern rtl_opt_pass *make_pass_rtl_loop_done (gcc::context *ctxt); extern rtl_opt_pass *make_pass_lower_subreg2 (gcc::context *ctxt); +extern rtl_opt_pass *make_pass_web_ssa (gcc::context *ctxt); extern rtl_opt_pass *make_pass_web (gcc::context *ctxt); extern rtl_opt_pass *make_pass_cse2 (gcc::context *ctxt); extern rtl_opt_pass *make_pass_df_initialize_opt (gcc::context *ctxt); diff --git a/gcc/web.cc b/gcc/web.cc index 9ab4ed62c744..dc9689ab96d9 100644 --- a/gcc/web.cc +++ b/gcc/web.cc @@ -29,17 +29,23 @@ along with GCC; see the file COPYING3. If not see we expand only if the induction variable is dead afterward, which is often the case). */ +#define INCLUDE_ALGORITHM +#define INCLUDE_FUNCTIONAL +#define INCLUDE_ARRAY #include "config.h" #include "system.h" #include "coretypes.h" #include "backend.h" #include "rtl.h" #include "df.h" +#include "rtl-ssa.h" +#include "cfgcleanup.h" #include "insn-config.h" #include "recog.h" #include "tree-pass.h" +using namespace rtl_ssa; /* Find the root of unionfind tree (the representative of set). */ @@ -427,3 +433,119 @@ make_pass_web (gcc::context *ctxt) { return new pass_web (ctxt); } + +namespace { + +#include <functional> + +static void +union_match_dups (insn_info *insn, web_entry *def_entry, web_entry *use_entry, + std::function<bool(web_entry_base *, web_entry_base *)> unite) +{ + rtx_insn *rtl = insn->rtl (); + if (insn->is_phi()) + { + // TODO: we should add phi input to the same web + return; + } + + if (!rtl) + return; + + extract_insn (rtl); + + struct web_entry *dup_entry; + for (int i = 0; i < recog_data.n_dups; ++i) + { + int op = recog_data.dup_num[i]; + enum op_type type = recog_data.operand_type[op]; + + dup_entry = use_entry; + // TODO: how to obtain loc from rtl ssa? + for (use_info *use : insn->uses ()) + if (use->reg() == *recog_data.dup_loc[i]) + break; + + + } +} + +const pass_data pass_data_web_ssa = +{ + RTL_PASS, /* type */ + "web-ssa", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_WEB, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_df_finish, /* todo_flags_finish */ +}; + +class pass_web_ssa : public rtl_opt_pass +{ +public: + pass_web_ssa (gcc::context *ctxt) + : rtl_opt_pass (pass_data_web_ssa, ctxt) + {} + + /* opt_pass methods: */ + bool gate (function *) final override { return (optimize > 0 && flag_web); } + unsigned int execute (function *) final override; + +}; // class pass_web + +unsigned int +pass_web_ssa::execute (function *fun) +{ + crtl->ssa = new rtl_ssa::function_info (fun); + unsigned int defs_num = 0; + unsigned int uses_num = 0; + + for (insn_info* insn : crtl->ssa->nondebug_insns ()) + { + for (def_info *def : insn->defs ()) + if (def->is_reg () && def->regno () >= FIRST_PSEUDO_REGISTER) + def->uid() = defs_num++; + + for (use_info *use : insn->uses ()) + if (use->is_reg () && use->regno () >= FIRST_PSEUDO_REGISTER) + use->uid() = uses_num++; + + // reg notes (aka eq_uses) - already handled - see access_info::only_occurs_in_notes () + } + + web_entry *def_entry = XCNEWVEC(web_entry, defs_num); + web_entry *use_entry = XCNEWVEC(web_entry, uses_num); + + const unsigned int max_reg = max_reg_num(); + unsigned int *used_regs = XCNEWVEC (unsigned, max_reg); + + for (insn_info* insn : crtl->ssa->nondebug_insns ()) + { + union_match_dups (insn, def_entry, use_entry, unionfind_union); + for (use_info *use : insn->uses ()) + if (use->regno() >= FIRST_PSEUDO_REGISTER) + {} + } + + free (def_entry); + free (use_entry); + free (used_regs); + + free_dominance_info (CDI_DOMINATORS); + if (crtl->ssa->perform_pending_updates ()) + cleanup_cfg (0); + + delete crtl->ssa; + crtl->ssa = nullptr; +} + +} + +rtl_opt_pass * +make_pass_web_ssa (gcc::context *ctxt) +{ + return new pass_web_ssa (ctxt); +} \ No newline at end of file