diff options
-rw-r--r-- | gcc/Makefile.in | 1 | ||||
-rw-r--r-- | gcc/rtl-ssa/access-utils.h | 41 | ||||
-rw-r--r-- | gcc/rtl-ssa/accesses.cc | 63 | ||||
-rw-r--r-- | gcc/rtl-ssa/movement.cc | 40 | ||||
-rw-r--r-- | gcc/rtl-ssa/movement.h | 4 |
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.) |