[3/3] rtl-ssa: Add new helper functions
Checks
Commit Message
This patch adds some RTL-SSA helper functions. They will be
used by the upcoming late-combine pass.
The patch contains the first non-template out-of-line function declared
in movement.h, so it adds a movement.cc. I realise it seems a bit
over-the-top to have a file with just one function, but it might grow
in future. :)
gcc/
* Makefile.in (OBJS): Add rtl-ssa/movement.o.
* rtl-ssa/access-utils.h (accesses_include_nonfixed_hard_registers)
(single_set_info): New functions.
(remove_uses_of_def, accesses_reference_same_resource): Declare.
(insn_clobbers_resources): Likewise.
* rtl-ssa/accesses.cc (rtl_ssa::remove_uses_of_def): New function.
(rtl_ssa::accesses_reference_same_resource): Likewise.
(rtl_ssa::insn_clobbers_resources): Likewise.
* rtl-ssa/movement.h (can_move_insn_p): Declare.
* rtl-ssa/movement.cc: New file.
---
gcc/Makefile.in | 1 +
gcc/rtl-ssa/access-utils.h | 41 +++++++++++++++++++++++++
gcc/rtl-ssa/accesses.cc | 63 ++++++++++++++++++++++++++++++++++++++
gcc/rtl-ssa/movement.cc | 40 ++++++++++++++++++++++++
gcc/rtl-ssa/movement.h | 4 +++
5 files changed, 149 insertions(+)
create mode 100644 gcc/rtl-ssa/movement.cc
Comments
On 10/24/23 11:58, Richard Sandiford wrote:
> This patch adds some RTL-SSA helper functions. They will be
> used by the upcoming late-combine pass.
>
> The patch contains the first non-template out-of-line function declared
> in movement.h, so it adds a movement.cc. I realise it seems a bit
> over-the-top to have a file with just one function, but it might grow
> in future. :)
>
> gcc/
> * Makefile.in (OBJS): Add rtl-ssa/movement.o.
> * rtl-ssa/access-utils.h (accesses_include_nonfixed_hard_registers)
> (single_set_info): New functions.
> (remove_uses_of_def, accesses_reference_same_resource): Declare.
> (insn_clobbers_resources): Likewise.
> * rtl-ssa/accesses.cc (rtl_ssa::remove_uses_of_def): New function.
> (rtl_ssa::accesses_reference_same_resource): Likewise.
> (rtl_ssa::insn_clobbers_resources): Likewise.
> * rtl-ssa/movement.h (can_move_insn_p): Declare.
> * rtl-ssa/movement.cc: New file.
I assumed that you'll end up with more code in there, so I'm certainly
OK with having just one function in the file right now.
OK for the trunk.
jeff
@@ -1635,6 +1635,7 @@ OBJS = \
rtl-ssa/changes.o \
rtl-ssa/functions.o \
rtl-ssa/insns.o \
+ rtl-ssa/movement.o \
rtl-tests.o \
rtl.o \
rtlhash.o \
@@ -33,6 +33,20 @@ accesses_include_hard_registers (const access_array &accesses)
return accesses.size () && HARD_REGISTER_NUM_P (accesses.front ()->regno ());
}
+// Return true if ACCESSES includes a reference to a non-fixed hard register.
+inline bool
+accesses_include_nonfixed_hard_registers (access_array accesses)
+{
+ for (access_info *access : accesses)
+ {
+ if (!HARD_REGISTER_NUM_P (access->regno ()))
+ break;
+ if (!fixed_regs[access->regno ()])
+ return true;
+ }
+ return false;
+}
+
// Return true if sorted array ACCESSES includes an access to memory.
inline bool
accesses_include_memory (const access_array &accesses)
@@ -246,6 +260,22 @@ last_def (def_mux mux)
return mux.last_def ();
}
+// If INSN's definitions contain a single set, return that set, otherwise
+// return null.
+inline set_info *
+single_set_info (insn_info *insn)
+{
+ set_info *set = nullptr;
+ for (auto def : insn->defs ())
+ if (auto this_set = dyn_cast<set_info *> (def))
+ {
+ if (set)
+ return nullptr;
+ set = this_set;
+ }
+ return set;
+}
+
int lookup_use (splay_tree<use_info *> &, insn_info *);
int lookup_def (def_splay_tree &, insn_info *);
int lookup_clobber (clobber_tree &, insn_info *);
@@ -539,6 +569,10 @@ insert_access (obstack_watermark &watermark,
return T (insert_access_base (watermark, access1, accesses2));
}
+// Return a copy of USES that drops any use of DEF.
+use_array remove_uses_of_def (obstack_watermark &, use_array uses,
+ def_info *def);
+
// The underlying non-template implementation of remove_note_accesses.
access_array remove_note_accesses_base (obstack_watermark &, access_array);
@@ -554,4 +588,11 @@ remove_note_accesses (obstack_watermark &watermark, T accesses)
return T (remove_note_accesses_base (watermark, accesses));
}
+// Return true if ACCESSES1 and ACCESSES2 have at least one resource in common.
+bool accesses_reference_same_resource (access_array accesses1,
+ access_array accesses2);
+
+// Return true if INSN clobbers the value of any resources in ACCESSES.
+bool insn_clobbers_resources (insn_info *insn, access_array accesses);
+
}
@@ -1569,6 +1569,19 @@ rtl_ssa::insert_access_base (obstack_watermark &watermark,
return builder.finish ();
}
+// See the comment above the declaration.
+use_array
+rtl_ssa::remove_uses_of_def (obstack_watermark &watermark, use_array uses,
+ def_info *def)
+{
+ access_array_builder uses_builder (watermark);
+ uses_builder.reserve (uses.size ());
+ for (use_info *use : uses)
+ if (use->def () != def)
+ uses_builder.quick_push (use);
+ return use_array (uses_builder.finish ());
+}
+
// See the comment above the declaration.
access_array
rtl_ssa::remove_note_accesses_base (obstack_watermark &watermark,
@@ -1587,6 +1600,56 @@ rtl_ssa::remove_note_accesses_base (obstack_watermark &watermark,
return accesses;
}
+// See the comment above the declaration.
+bool
+rtl_ssa::accesses_reference_same_resource (access_array accesses1,
+ access_array accesses2)
+{
+ auto i1 = accesses1.begin ();
+ auto end1 = accesses1.end ();
+ auto i2 = accesses2.begin ();
+ auto end2 = accesses2.end ();
+
+ while (i1 != end1 && i2 != end2)
+ {
+ access_info *access1 = *i1;
+ access_info *access2 = *i2;
+
+ unsigned int regno1 = access1->regno ();
+ unsigned int regno2 = access2->regno ();
+ if (regno1 == regno2)
+ return true;
+
+ if (regno1 < regno2)
+ ++i1;
+ else
+ ++i2;
+ }
+ return false;
+}
+
+// See the comment above the declaration.
+bool
+rtl_ssa::insn_clobbers_resources (insn_info *insn, access_array accesses)
+{
+ if (accesses_reference_same_resource (insn->defs (), accesses))
+ return true;
+
+ if (insn->is_call () && accesses_include_hard_registers (accesses))
+ {
+ function_abi abi = insn_callee_abi (insn->rtl ());
+ for (const access_info *access : accesses)
+ {
+ if (!HARD_REGISTER_NUM_P (access->regno ()))
+ break;
+ if (abi.clobbers_reg_p (access->mode (), access->regno ()))
+ return true;
+ }
+ }
+
+ return false;
+}
+
// Print RESOURCE to PP.
void
rtl_ssa::pp_resource (pretty_printer *pp, resource_info resource)
new file mode 100644
@@ -0,0 +1,40 @@
+// RTL SSA routines for moving instructions
+// Copyright (C) 2023 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "df.h"
+#include "rtl-ssa.h"
+#include "rtl-ssa/internals.h"
+#include "rtl-ssa/internals.inl"
+
+using namespace rtl_ssa;
+
+// See the comment above the declaration.
+bool
+rtl_ssa::can_move_insn_p (insn_info *insn)
+{
+ return (!control_flow_insn_p (insn->rtl ())
+ && !may_trap_p (PATTERN (insn->rtl ())));
+}
@@ -19,6 +19,10 @@
namespace rtl_ssa {
+// Return true if INSN can in principle be moved around, and if RTL-SSA
+// has enough information to do that.
+bool can_move_insn_p (insn_info *);
+
// Restrict movement range RANGE so that the instruction is placed later
// than INSN. (The movement range is the range of instructions after which
// an instruction can be placed.)