Hi Dimitar

I send a patch just now, modifies accordingly


some comments:


>Nit: Should have two spaces after the dot, per GNU coding style.  I'd 
suggest
>to run the contrib/check_GNU_style.py script on your patches.
Do you mean "star" by "dot", i.e. "/*----" should be "/* ----"?


>These names seem a bit too short for global variables.  Perhaps tuck
>them in a namespace?
>
>Also, since these must remain empty, shouldn't they be declared as const?
>
>namespace df {
>   const bitmap_head empty_bitmap;
>   const subregs_live empty_live;
>}



May be better if "namespace df" contains all DF related code? as a minor 
modification, I add a prefix "df_" to the variables.
Meanwhile, const seems inapropriate here, since it's returned as normal pointer 
rather than const pointer in some funtions, 

change to const would break this return value type check, and a const_cast 
would make the const meanlingless.


more details see in the patch


regards
Shuo

 
 
------------------ Original ------------------
From: &nbsp;"Dimitar&nbsp;Dimitrov"<dimi...@dinux.eu&gt;;
Date: &nbsp;Fri, Apr 26, 2024 04:56 AM
To: &nbsp;"Lehua Ding"<lehua.d...@rivai.ai&gt;; 
Cc: &nbsp;"gcc-patches"<gcc-patches@gcc.gnu.org&gt;; 
"juzhe.zhong"<juzhe.zh...@rivai.ai&gt;; "shuo.chen"<shuo.c...@rivai.ai&gt;; 
"jin.xia"<jin....@rivai.ai&gt;; "vmakarov"<vmaka...@redhat.com&gt;; 
"richard.sandiford"<richard.sandif...@arm.com&gt;; 
Subject: &nbsp;Re: [PATCH 2/4] df: Add DF_LIVE_SUBREG problem

&nbsp;

On Wed, Apr 24, 2024 at 06:05:03PM +0800, Lehua Ding wrote:
&gt; This patch add a new DF problem, named DF_LIVE_SUBREG. This problem
&gt; is extended from the DF_LR problem and support track the subreg liveness
&gt; of multireg pseudo if these pseudo satisfy the following conditions:
&gt; 
&gt;&nbsp;&nbsp; 1. the mode size greater than it's REGMODE_NATURAL_SIZE.
&gt;&nbsp;&nbsp; 2. the reg is used in insns via subreg pattern.
&gt; 
&gt; The main methods are as follows:
&gt; 
&gt;&nbsp;&nbsp; 1. split bitmap in/out/def/use fileds to full_in/out/def/use 
and
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; partial_in/out/def/use. If a pseudo need to 
be tracked it's subreg
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; liveness, then it is recorded in 
partial_in/out/def/use fileds.
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Meantimes, there are range_in/out/def/use 
fileds which records the live
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; range of the tracked pseudo.
&gt;&nbsp;&nbsp; 2. in the df_live_subreg_finalize function, we move the 
tracked pseudo from
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the partial_in/out/def/use to 
full_in/out/def/use if the pseudo's live
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; range is full.

Hi Lehua,

I'm not familiar with LRA, so my comments bellow could be totally off
point.&nbsp; Please treat them as mild suggestions.

&gt; 
&gt; gcc/ChangeLog:
&gt; 
&gt;    * Makefile.in: Add subreg-live-range object file.
&gt;    * df-problems.cc (struct df_live_subreg_problem_data): Private struct
&gt;    for DF_LIVE_SUBREG problem.
&gt;    (df_live_subreg_get_bb_info): getting bb regs in/out data.
&gt;    (get_live_subreg_local_bb_info): getting bb regs use/def data.
&gt;    (multireg_p): checking is the regno a pseudo multireg.
&gt;    (need_track_subreg_p): checking is the regno need to be tracked.
&gt;    (init_range): getting the range of subreg rtx.
&gt;    (remove_subreg_range): removing use data for the reg/subreg rtx.
&gt;    (add_subreg_range): adding def/use data for the reg/subreg rtx.
&gt;    (df_live_subreg_free_bb_info): Free basic block df data.
&gt;    (df_live_subreg_alloc): Allocate and init df data.
&gt;    (df_live_subreg_reset): Reset the live in/out df data.
&gt;    (df_live_subreg_bb_local_compute): Compute basic block df data.
&gt;    (df_live_subreg_local_compute): Compute all basic blocks df data.
&gt;    (df_live_subreg_init): Init the in/out df data.
&gt;    (df_live_subreg_check_result): Assert the full and partial df data.
&gt;    (df_live_subreg_confluence_0): Confluence function for infinite loops.
&gt;    (df_live_subreg_confluence_n): Confluence function for normal edge.
&gt;    (df_live_subreg_transfer_function): Transfer function.
&gt;    (df_live_subreg_finalize): Finalize the all_in/all_out df data.
&gt;    (df_live_subreg_free): Free the df data.
&gt;    (df_live_subreg_top_dump): Dump top df data.
&gt;    (df_live_subreg_bottom_dump): Dump bottom df data.
&gt;    (df_live_subreg_add_problem): Add the DF_LIVE_SUBREG problem.
&gt;    * df.h (enum df_problem_id): Add DF_LIVE_SUBREG.
&gt;    (class subregs_live): Simple decalare.
&gt;    (class df_live_subreg_local_bb_info): New class for full/partial def/use
&gt;    df data.
&gt;    (class df_live_subreg_bb_info): New class for full/partial in/out
&gt;    df data.
&gt;    (df_live_subreg): getting the df_live_subreg data.
&gt;    (df_live_subreg_add_problem): Exported.
&gt;    (df_live_subreg_finalize): Ditto.
&gt;    (df_live_subreg_check_result): Ditto.
&gt;    (multireg_p): Ditto.
&gt;    (init_range): Ditto.
&gt;    (add_subreg_range): Ditto.
&gt;    (remove_subreg_range): Ditto.
&gt;    (df_get_subreg_live_in): Accessor the all_in df data.
&gt;    (df_get_subreg_live_out): Accessor the all_out df data.
&gt;    (df_get_subreg_live_full_in): Accessor the full_in df data.
&gt;    (df_get_subreg_live_full_out): Accessor the full_out df data.
&gt;    (df_get_subreg_live_partial_in): Accessor the partial_in df data.
&gt;    (df_get_subreg_live_partial_out): Accessor the partial_out df data.
&gt;    (df_get_subreg_live_range_in): Accessor the range_in df data.
&gt;    (df_get_subreg_live_range_out): Accessor the range_out df data.
&gt;    * regs.h (get_nblocks): Get the blocks of mode.
&gt;    * sbitmap.cc (bitmap_full_p): sbitmap predicator.
&gt;    (bitmap_same_p): sbitmap predicator.
&gt;    (test_full): test bitmap_full_p.
&gt;    (test_same): test bitmap_same_p.
&gt;    (sbitmap_cc_tests): Add test_full and test_same.
&gt;    * sbitmap.h (bitmap_full_p): Exported.
&gt;    (bitmap_same_p): Ditto.
&gt;    * timevar.def (TV_DF_LIVE_SUBREG): add DF_LIVE_SUBREG timevar.
&gt;    * subreg-live-range.cc: New file.
&gt;    * subreg-live-range.h: New file.
&gt; ---
&gt;&nbsp; 
gcc/Makefile.in&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|&nbsp;&nbsp; 1 +
&gt;&nbsp; gcc/df-problems.cc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 855 
++++++++++++++++++++++++++++++++++++++-
&gt;&nbsp; 
gcc/df.h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 | 155 +++++++
&gt;&nbsp; 
gcc/regs.h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 |&nbsp;&nbsp; 5 +
&gt;&nbsp; 
gcc/sbitmap.cc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|&nbsp; 98 +++++
&gt;&nbsp; 
gcc/sbitmap.h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|&nbsp;&nbsp; 2 +
&gt;&nbsp; gcc/subreg-live-range.cc |&nbsp; 53 +++
&gt;&nbsp; gcc/subreg-live-range.h&nbsp; | 206 ++++++++++
&gt;&nbsp; 
gcc/timevar.def&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|&nbsp;&nbsp; 1 +
&gt;&nbsp; 9 files changed, 1375 insertions(+), 1 deletion(-)
&gt;&nbsp; create mode 100644 gcc/subreg-live-range.cc
&gt;&nbsp; create mode 100644 gcc/subreg-live-range.h
&gt; 
&gt; diff --git a/gcc/Makefile.in b/gcc/Makefile.in
&gt; index a74761b7ab3..e195238f6ab 100644
&gt; --- a/gcc/Makefile.in
&gt; +++ b/gcc/Makefile.in
&gt; @@ -1684,6 +1684,7 @@ OBJS = \
&gt;&nbsp;      store-motion.o \
&gt;&nbsp;      streamer-hooks.o \
&gt;&nbsp;      stringpool.o \
&gt; +  subreg-live-range.o \
&gt;&nbsp;      substring-locations.o \
&gt;&nbsp;      target-globals.o \
&gt;&nbsp;      targhooks.o \
&gt; diff --git a/gcc/df-problems.cc b/gcc/df-problems.cc
&gt; index 88ee0dd67fc..93c5b52146c 100644
&gt; --- a/gcc/df-problems.cc
&gt; +++ b/gcc/df-problems.cc
&gt; @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.&nbsp; If not see
&gt;&nbsp; #include "target.h"
&gt;&nbsp; #include "rtl.h"
&gt;&nbsp; #include "df.h"
&gt; +#include "subreg-live-range.h"
&gt;&nbsp; #include "memmodel.h"
&gt;&nbsp; #include "tm_p.h"
&gt;&nbsp; #include "insn-config.h"
&gt; @@ -1344,8 +1345,860 @@ df_lr_verify_transfer_functions (void)
&gt;&nbsp;&nbsp;&nbsp; bitmap_clear (&amp;all_blocks);
&gt;&nbsp; }
&gt;&nbsp; 
&gt; 
+/*----------------------------------------------------------------------------
&gt; +&nbsp;&nbsp; REGISTER AND SUBREGS LIVES
&gt; +&nbsp;&nbsp; Like DF_LR, but include tracking subreg liveness. Currently 
used to provide
Nit: Should have two spaces after the dot, per GNU coding style.&nbsp; I'd 
suggest
to run the contrib/check_GNU_style.py script on your patches.

&gt; +&nbsp;&nbsp; subreg liveness related information to the register 
allocator. The subreg
&gt; +&nbsp;&nbsp; information is currently tracked for registers that satisfy 
the following
&gt; +&nbsp;&nbsp; conditions:
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; 1. REG is a pseudo register
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; 2. MODE_SIZE &gt; UNIT_SIZE
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; 3. MODE_SIZE is a multiple of UNIT_SIZE
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; 4. REG is used via subreg pattern
&gt; +&nbsp;&nbsp; Assuming: MODE = the machine mode of the REG
&gt; +  &nbsp;&nbsp;&nbsp;&nbsp; MODE_SIZE = GET_MODE_SIZE (MODE)
&gt; +  &nbsp;&nbsp;&nbsp;&nbsp; UNIT_SIZE = REGMODE_NATURAL_SIZE (MODE)
&gt; +&nbsp;&nbsp; Condition 3 is currently strict, maybe it can be removed in 
the future, but
&gt; +&nbsp;&nbsp; for now it is sufficient.
&gt; +&nbsp;&nbsp; 
----------------------------------------------------------------------------*/
&gt; +
&gt; +/* These two empty data are used as default data in case the user does 
not turn
&gt; + * on the track-subreg-liveness feature.&nbsp; */
&gt; +bitmap_head empty_bitmap;
&gt; +subregs_live empty_live;
These names seem a bit too short for global variables.&nbsp; Perhaps tuck
them in a namespace?

Also, since these must remain empty, shouldn't they be declared as const?

namespace df {
&nbsp;&nbsp; const bitmap_head empty_bitmap;
&nbsp;&nbsp; const subregs_live empty_live;
}


&gt; +
&gt; +/* Private data for live_subreg problem.&nbsp; */
&gt; +struct df_live_subreg_problem_data
&gt; +{
&gt; +&nbsp; /* Record registers that need to track subreg liveness.&nbsp; */
&gt; +&nbsp; bitmap_head tracked_regs;
&gt; +&nbsp; /* An obstack for the bitmaps we need for this problem.&nbsp; */
&gt; +&nbsp; bitmap_obstack live_subreg_bitmaps;
&gt; +};
&gt; +
&gt; +/* Helper functions */
&gt; +
&gt; +static df_live_subreg_bb_info *
&gt; +df_live_subreg_get_bb_info (unsigned int index)
&gt; +{
&gt; +&nbsp; if (index < df_live_subreg-&gt;block_info_size)
&gt; +&nbsp;&nbsp;&nbsp; return &amp;(
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (class df_live_subreg_bb_info *) 
df_live_subreg-&gt;block_info)[index];
Please consider using C++ instead:
&nbsp;&nbsp; return &amp;static_cast<df_live_subreg_bb_info 
*&gt;(df_live_subreg-&gt;block_info)[index];

&gt; +&nbsp; else
&gt; +&nbsp;&nbsp;&nbsp; return NULL;
Use nullptr instead?

&gt; +}
&gt; +
&gt; +static df_live_subreg_local_bb_info *
&gt; +get_live_subreg_local_bb_info (unsigned int bb_index)
&gt; +{
&gt; +&nbsp; return df_live_subreg_get_bb_info (bb_index);
&gt; +}
&gt; +
&gt; +/* Return true if regno is a multireg.&nbsp; */
&gt; +bool
&gt; +multireg_p (int regno)
&gt; +{
&gt; +&nbsp; if (regno < FIRST_PSEUDO_REGISTER)
&gt; +&nbsp;&nbsp;&nbsp; return false;
&gt; +&nbsp; rtx regno_rtx = regno_reg_rtx[regno];
&gt; +&nbsp; machine_mode reg_mode = GET_MODE (regno_rtx);
&gt; +&nbsp; poly_int64 total_size = GET_MODE_SIZE (reg_mode);
&gt; +&nbsp; poly_int64 natural_size = REGMODE_NATURAL_SIZE (reg_mode);
&gt; +&nbsp; return maybe_gt (total_size, natural_size)
&gt; +   &amp;&amp; multiple_p (total_size, natural_size);
&gt; +}
&gt; +
&gt; +/* Return true if the REGNO need be track with subreg liveness.&nbsp; */
&gt; +
&gt; +static bool
&gt; +need_track_subreg_p (unsigned regno)
&gt; +{
&gt; +&nbsp; struct df_live_subreg_problem_data *problem_data
&gt; +&nbsp;&nbsp;&nbsp; = (struct df_live_subreg_problem_data *) 
df_live_subreg-&gt;problem_data;

Here auto could be used:

&nbsp;&nbsp;&nbsp; auto problem_data = (struct df_live_subreg_problem_data *) 
df_live_subreg-&gt;problem_data;

&gt; +&nbsp; return bitmap_bit_p (&amp;problem_data-&gt;tracked_regs, regno);
&gt; +}
&gt; +
&gt; +/* Return the subreg_range of REF.&nbsp; */
Is this comment valid? I see neither a REF parameter, nor a returned
value.&nbsp; Did you perhaps mean:
&nbsp; /* Fill RANGE with the subreg range for OP in REGMODE_NATURAL_SIZE
&nbsp;&nbsp;&nbsp;&nbsp; granularity.&nbsp; */

&gt; +void
&gt; +init_range (rtx op, sbitmap range)
&gt; +{
&gt; +&nbsp; rtx reg = SUBREG_P (op) ? SUBREG_REG (op) : op;
&gt; +&nbsp; machine_mode reg_mode = GET_MODE (reg);
&gt; +
&gt; +&nbsp; if (!read_modify_subreg_p (op))
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_set_range (range, 0, get_nblocks 
(reg_mode));
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +
&gt; +&nbsp; rtx subreg = op;
&gt; +&nbsp; machine_mode subreg_mode = GET_MODE (subreg);
&gt; +&nbsp; poly_int64 offset = SUBREG_BYTE (subreg);
&gt; +&nbsp; int nblocks = get_nblocks (reg_mode);
&gt; +&nbsp; poly_int64 unit_size = REGMODE_NATURAL_SIZE (reg_mode);
&gt; +&nbsp; poly_int64 subreg_size = GET_MODE_SIZE (subreg_mode);
&gt; +&nbsp; poly_int64 left = offset + subreg_size;
&gt; +
&gt; +&nbsp; int subreg_start = -1;
&gt; +&nbsp; int subreg_nblocks = -1;
&gt; +&nbsp; for (int i = 0; i < nblocks; i += 1)
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; poly_int64 right = unit_size * (i + 1);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (subreg_start < 0 &amp;&amp; maybe_lt 
(offset, right))
&gt; +  subreg_start = i;
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (subreg_nblocks < 0 &amp;&amp; maybe_le 
(left, right))
&gt; +  {
&gt; +  &nbsp; subreg_nblocks = i + 1 - subreg_start;
&gt; +  &nbsp; break;
&gt; +  }
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +&nbsp; gcc_assert (subreg_start &gt;= 0 &amp;&amp; subreg_nblocks &gt; 0);
&gt; +
&gt; +&nbsp; bitmap_set_range (range, subreg_start, subreg_nblocks);
&gt; +}
&gt; +
&gt; +/* Remove RANGE from BB_INFO's use data.&nbsp; */
&gt; +void
&gt; +remove_subreg_range (df_live_subreg_local_bb_info *bb_info, unsigned int 
regno,
&gt; +          &nbsp;&nbsp;&nbsp;&nbsp; const_sbitmap range)
&gt; +{
&gt; +&nbsp; bitmap partial = &amp;bb_info-&gt;partial_use;
&gt; +
&gt; +&nbsp; bb_info-&gt;range_use-&gt;remove_range (regno, range);
&gt; +&nbsp; if (bb_info-&gt;range_use-&gt;empty_p (regno))
&gt; +&nbsp;&nbsp;&nbsp; bitmap_clear_bit (partial, regno);
&gt; +}
&gt; +
&gt; +/* Remove RANGE of REF from BB_INFO's use data.&nbsp; */
&gt; +static void
&gt; +remove_subreg_range (df_live_subreg_local_bb_info *bb_info, df_ref ref)
&gt; +{
&gt; +&nbsp; unsigned int regno = DF_REF_REGNO (ref);
&gt; +&nbsp; machine_mode reg_mode = GET_MODE (DF_REF_REAL_REG (ref));
&gt; +
&gt; +&nbsp; if (need_track_subreg_p (regno))
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_sbitmap range (get_nblocks 
(reg_mode));
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; init_range (DF_REF_REG (ref), range);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remove_subreg_range (bb_info, regno, 
range);
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +&nbsp; else
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_clear_bit 
(&amp;bb_info-&gt;full_use, regno);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gcc_assert (!bitmap_bit_p 
(&amp;bb_info-&gt;partial_use, regno));
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gcc_assert (!bitmap_bit_p 
(&amp;bb_info-&gt;partial_def, regno));
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +}
&gt; +
&gt; +/* add RANGE to BB_INFO's def/use. If is_def is true, means for BB_INFO's 
def,
&gt; +&nbsp;&nbsp; otherwise for BB_INFO's use.&nbsp; */
&gt; +void
&gt; +add_subreg_range (df_live_subreg_local_bb_info *bb_info, unsigned int 
regno,
&gt; +          &nbsp; const_sbitmap range, bool is_def)
Would it be more clear to split into two separate functions
instead of using a boolean flag? E.g.:
&nbsp; add_subreg_range_to_def (df_live_subreg_local_bb_info *bb_info, unsigned 
int regno,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 const_sbitmap range)
&nbsp; add_subreg_range_to_use (df_live_subreg_local_bb_info *bb_info, unsigned 
int regno,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 const_sbitmap range)

&gt; +{
&gt; +&nbsp; bitmap partial = is_def ? &amp;bb_info-&gt;partial_def : 
&amp;bb_info-&gt;partial_use;
&gt; +&nbsp; subregs_live *range_live = is_def ? bb_info-&gt;range_def : 
bb_info-&gt;range_use;
&gt; +
&gt; +&nbsp; bitmap_set_bit (partial, regno);
&gt; +&nbsp; range_live-&gt;add_range (regno, range);
&gt; +}
&gt; +
&gt; +/* add RANGE of REF to BB_INFO def/use. If is_def is true, means for 
BB_INFO's
&gt; +&nbsp;&nbsp; def, otherwise for BB_INFO's use.&nbsp; */
&gt; +static void
&gt; +add_subreg_range (df_live_subreg_local_bb_info *bb_info, df_ref ref,
&gt; +          &nbsp; bool is_def)
&gt; +{
&gt; +&nbsp; unsigned int regno = DF_REF_REGNO (ref);
&gt; +&nbsp; machine_mode reg_mode = GET_MODE (DF_REF_REAL_REG (ref));
&gt; +
&gt; +&nbsp; if (need_track_subreg_p (regno))
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_sbitmap range (get_nblocks 
(reg_mode));
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; init_range (DF_REF_REG (ref), range);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add_subreg_range (bb_info, regno, range, 
is_def);
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +&nbsp; else
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap full = is_def ? 
&amp;bb_info-&gt;full_def : &amp;bb_info-&gt;full_use;
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap partial = is_def ? 
&amp;bb_info-&gt;partial_def : &amp;bb_info-&gt;partial_use;
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_set_bit (full, regno);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gcc_assert (!bitmap_bit_p (partial, 
regno));
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +}
&gt; +
&gt; +/* Free basic block info.&nbsp; */
&gt; +
&gt; +static void
&gt; +df_live_subreg_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, void 
*vbb_info)
&gt; +{
&gt; +&nbsp; df_live_subreg_bb_info *bb_info = (df_live_subreg_bb_info *) 
vbb_info;
Perhaps:
&nbsp;&nbsp;&nbsp;&nbsp; auto bb_info = static_cast<df_live_subreg_bb_info 
*&gt; vbb_info;

&gt; +&nbsp; if (bb_info)
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete bb_info-&gt;range_in;
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bb_info-&gt;range_in = NULL;
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete bb_info-&gt;range_out;
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bb_info-&gt;range_out = NULL;
&gt; +
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_clear (&amp;bb_info-&gt;all_in);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_clear (&amp;bb_info-&gt;full_in);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_clear (&amp;bb_info-&gt;partial_in);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_clear (&amp;bb_info-&gt;all_out);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_clear (&amp;bb_info-&gt;full_out);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_clear 
(&amp;bb_info-&gt;partial_out);
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +}
&gt; +
&gt; +/* Allocate or reset bitmaps for DF_LIVE_SUBREG blocks. The solution bits 
are
&gt; +&nbsp;&nbsp; not touched unless the block is new.&nbsp; */
&gt; +
&gt; +static void
&gt; +df_live_subreg_alloc (bitmap all_blocks ATTRIBUTE_UNUSED)
&gt; +{
&gt; +&nbsp; struct df_live_subreg_problem_data *problem_data;
&gt; +&nbsp; df_grow_bb_info (df_live_subreg);
&gt; +&nbsp; if (df_live_subreg-&gt;problem_data)
&gt; +&nbsp;&nbsp;&nbsp; problem_data
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = (struct df_live_subreg_problem_data *) 
df_live_subreg-&gt;problem_data;
&gt; +&nbsp; else
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; problem_data = XNEW (struct 
df_live_subreg_problem_data);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; df_live_subreg-&gt;problem_data = 
problem_data;
&gt; +
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_obstack_initialize 
(&amp;problem_data-&gt;live_subreg_bitmaps);
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap_initialize 
(&amp;problem_data-&gt;tracked_regs,
&gt; +                   &amp;problem_data-&gt;live_subreg_bitmaps);
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +
&gt; +&nbsp; bitmap_clear (&amp;problem_data-&gt;tracked_regs);
&gt; +
&gt; +&nbsp; basic_block bb;
&gt; +&nbsp; FOR_EACH_BB_FN (bb, cfun)
&gt; +&nbsp;&nbsp;&nbsp; bitmap_set_bit 
(df_live_subreg-&gt;out_of_date_transfer_functions, bb-&gt;index);
&gt; +
&gt; +&nbsp; bitmap_set_bit (df_live_subreg-&gt;out_of_date_transfer_functions, 
ENTRY_BLOCK);
&gt; +&nbsp; bitmap_set_bit (df_live_subreg-&gt;out_of_date_transfer_functions, 
EXIT_BLOCK);
&gt; +
&gt; +&nbsp; unsigned int bb_index;
&gt; +&nbsp; bitmap_iterator bi;
&gt; +&nbsp; EXECUTE_IF_SET_IN_BITMAP 
(df_live_subreg-&gt;out_of_date_transfer_functions, 0,
&gt; +                  &nbsp;&nbsp;&nbsp; bb_index, bi)
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Find the regs which we need to track 
it's subreg liveness.&nbsp; */
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rtx_insn *insn;
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; df_ref use;
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FOR_BB_INSNS (bb, insn)
&gt; +  {
&gt; +  &nbsp; if (!NONDEBUG_INSN_P (insn))
&gt; +  &nbsp;&nbsp;&nbsp; continue;
&gt; +
&gt; +  &nbsp; df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
&gt; +
&gt; +  &nbsp; FOR_EACH_INSN_INFO_USE (use, insn_info)
&gt; +  &nbsp;&nbsp;&nbsp; {
&gt; +  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int regno = DF_REF_REGNO (use);
&gt; 
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
/* A multireg which is used via subreg pattern.&nbsp; */
&gt; +  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (multireg_p (regno)
&gt; +          &nbsp; &amp;&amp; DF_REF_FLAGS (use) &amp; (DF_REF_SUBREG))
&gt; +          bitmap_set_bit (&amp;problem_data-&gt;tracked_regs, regno);
&gt; +  &nbsp;&nbsp;&nbsp; }
&gt; +  }
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +
&gt; +&nbsp; if (dump_file)
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf (dump_file, ";; regs need to be 
tracked subreg liveness: ");
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; df_print_regset (dump_file, 
&amp;problem_data-&gt;tracked_regs);
&gt; +&nbsp;&nbsp;&nbsp; }
&gt; +
&gt; +&nbsp; size_t n = bitmap_count_bits (&amp;problem_data-&gt;tracked_regs);
&gt; +
&gt; +&nbsp; EXECUTE_IF_SET_IN_BITMAP 
(df_live_subreg-&gt;out_of_date_transfer_functions, 0,
&gt; +                  &nbsp;&nbsp;&nbsp; bb_index, bi)
&gt; +&nbsp;&nbsp;&nbsp; {
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Clean global infos.&nbsp; */
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; df_live_subreg_bb_info *bb_info = 
df_live_subreg_get_bb_info (bb_index);

Here and for the rest of the call sites, I think auto is allowed to be used:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto bb_info = 
df_live_subreg_get_bb_info (bb_index);


Regards,
Dimitar

Reply via email to