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:
parent
39cac7c314
commit
cfb7755d10
5 changed files with 149 additions and 0 deletions
|
@ -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)
|
||||
|
|
40
gcc/rtl-ssa/movement.cc
Normal file
40
gcc/rtl-ssa/movement.cc
Normal 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 ())));
|
||||
}
|
|
@ -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.)
|
||||
|
|
Loading…
Add table
Reference in a new issue