rtl-ssa: Add new helper functions

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.
This commit is contained in:
Richard Sandiford 2023-10-25 10:39:53 +01:00
parent 39cac7c314
commit cfb7755d10
5 changed files with 149 additions and 0 deletions

View file

@ -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 \

View file

@ -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);
}

View file

@ -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)

40
gcc/rtl-ssa/movement.cc Normal file
View file

@ -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 ())));
}

View file

@ -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.)