aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/Makefile.in1
-rw-r--r--gcc/rtl-ssa/access-utils.h41
-rw-r--r--gcc/rtl-ssa/accesses.cc63
-rw-r--r--gcc/rtl-ssa/movement.cc40
-rw-r--r--gcc/rtl-ssa/movement.h4
5 files changed, 149 insertions, 0 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 7b7a4ff..91d6bfb 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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 \
diff --git a/gcc/rtl-ssa/access-utils.h b/gcc/rtl-ssa/access-utils.h
index 0d7a57f..f078625b 100644
--- a/gcc/rtl-ssa/access-utils.h
+++ b/gcc/rtl-ssa/access-utils.h
@@ -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);
+
}
diff --git a/gcc/rtl-ssa/accesses.cc b/gcc/rtl-ssa/accesses.cc
index 1b25ecc..510545a 100644
--- a/gcc/rtl-ssa/accesses.cc
+++ b/gcc/rtl-ssa/accesses.cc
@@ -1570,6 +1570,19 @@ rtl_ssa::insert_access_base (obstack_watermark &watermark,
}
// 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,
access_array accesses)
@@ -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)
diff --git a/gcc/rtl-ssa/movement.cc b/gcc/rtl-ssa/movement.cc
new file mode 100644
index 0000000..fcf5f8b
--- /dev/null
+++ b/gcc/rtl-ssa/movement.cc
@@ -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 ())));
+}
diff --git a/gcc/rtl-ssa/movement.h b/gcc/rtl-ssa/movement.h
index 6737094..ec076db 100644
--- a/gcc/rtl-ssa/movement.h
+++ b/gcc/rtl-ssa/movement.h
@@ -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.)