GCC Middle and Back End API Reference
ext-dce.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "tree.h"
#include "memmodel.h"
#include "insn-config.h"
#include "emit-rtl.h"
#include "recog.h"
#include "cfganal.h"
#include "tree-pass.h"
#include "cfgrtl.h"
#include "rtl-iter.h"
#include "df.h"
#include "print-rtl.h"
#include "dbgcnt.h"
Include dependency graph for ext-dce.cc:

Macros

#define UNSPEC_P(X)
 

Functions

static int group_limit (const_rtx reg)
 
static void make_reg_live (bitmap bmap, int regno)
 
static bool safe_for_live_propagation (rtx_code code)
 
static bool ext_dce_process_sets (rtx_insn *insn, rtx obj, bitmap live_tmp)
 
static void ext_dce_try_optimize_insn (rtx_insn *insn, rtx set)
 
static bool binop_implies_op2_fully_live (rtx_code code)
 
unsigned HOST_WIDE_INT carry_backpropagate (unsigned HOST_WIDE_INT mask, enum rtx_code code, rtx x)
 
static void ext_dce_process_uses (rtx_insn *insn, rtx obj, bitmap live_tmp, bool skipped_dest)
 
static void ext_dce_process_bb (basic_block bb)
 
static void maybe_clear_subreg_promoted_p (void)
 
static void reset_subreg_promoted_p (void)
 
static void ext_dce_init (void)
 
static void ext_dce_finish (void)
 
static bool ext_dce_rd_transfer_n (int bb_index)
 
static bool ext_dce_rd_confluence_n (edge)
 
void ext_dce_execute (void)
 
rtl_opt_passmake_pass_ext_dce (gcc::context *ctxt)
 

Variables

static vec< bitmap_headlivein
 
static bitmap all_blocks
 
static bitmap livenow
 
static bitmap changed_pseudos
 
static bool modify
 

Macro Definition Documentation

◆ UNSPEC_P

#define UNSPEC_P ( X)
Value:
(GET_CODE (X) == UNSPEC || GET_CODE (X) == UNSPEC_VOLATILE)
#define GET_CODE(RTX)
Definition rtl.h:726
Note this pass could be used to narrow memory loads too.  It's
not clear if that's profitable or not in general.   

Referenced by ext_dce_process_sets().

Function Documentation

◆ binop_implies_op2_fully_live()

static bool binop_implies_op2_fully_live ( rtx_code code)
static
Some operators imply that their second operand is fully live,
regardless of how many bits in the output are live.  An example
would be the shift count on a target without SHIFT_COUNT_TRUNCATED
defined.

Return TRUE if CODE is such an operator.  FALSE otherwise.   

References SHIFT_COUNT_TRUNCATED.

Referenced by ext_dce_process_uses().

◆ carry_backpropagate()

unsigned HOST_WIDE_INT carry_backpropagate ( unsigned HOST_WIDE_INT mask,
enum rtx_code code,
rtx x )
X, with code CODE, is an operation for which safe_for_live_propagation
holds true, and bits set in MASK are live in the result.  Compute a
mask of (potentially) live bits in the non-constant inputs.  In case of
binop_implies_op2_fully_live (e.g. shifts), the computed mask may
exclusively pertain to the first operand.

This looks wrong as we may have some important operations embedded as
operands of another operation.  For example, we might have an extension
wrapping a shift.  It really feels like this needs to be recursing down
into operands much more often.   

References carry_backpropagate(), clz_hwi(), const0_rtx, const1_rtx, CONST_INT_P, ctz_hwi(), exact_log2(), floor_log2(), GET_CODE, GET_MODE, GET_MODE_BITSIZE(), GET_MODE_INNER, GET_MODE_MASK, HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1U, HOST_WIDE_INT_UC, INTVAL, is_a(), pow2p_hwi(), poly_int< N, C >::to_constant(), UINTVAL, and XEXP.

Referenced by carry_backpropagate(), and ext_dce_process_uses().

◆ ext_dce_execute()

void ext_dce_execute ( void )
Use lifetime analyis to identify extensions that set bits that
are never read.  Turn such extensions into SUBREGs instead which
can often be propagated away.   

References all_blocks, df_analyze(), DF_BACKWARD, df_get_n_blocks(), df_get_postorder(), df_simple_dataflow(), ext_dce_finish(), ext_dce_init(), ext_dce_rd_confluence_n(), ext_dce_rd_transfer_n(), maybe_clear_subreg_promoted_p(), modify, NULL, and reset_subreg_promoted_p().

◆ ext_dce_finish()

static void ext_dce_finish ( void )
static
Finalization of the ext-dce pass.  Primarily this means
releasing up the various bitmaps we utilize.   

References all_blocks, bitmap_clear(), BITMAP_FREE, changed_pseudos, i, livein, and livenow.

Referenced by ext_dce_execute().

◆ ext_dce_init()

static void ext_dce_init ( void )
static
Initialization of the ext-dce pass.  Primarily this means
setting up the various bitmaps we utilize.   

References all_blocks, BITMAP_ALLOC, bitmap_default_obstack, bitmap_initialize(), bitmap_set_bit, cfun, changed_pseudos, df_get_exit_block_use_set(), ENTRY_BLOCK, EXECUTE_IF_SET_IN_BITMAP, EXIT_BLOCK, i, last_basic_block_for_fn, livein, livenow, make_reg_live(), modify, NULL, and refs.

Referenced by ext_dce_execute().

◆ ext_dce_process_bb()

static void ext_dce_process_bb ( basic_block bb)
static
Process a single basic block BB with current liveness information
in LIVENOW, returning updated liveness information.

If MODIFY is true, then this is the last pass and unnecessary
extensions should be eliminated when possible.  If an extension
is removed, the source pseudo is marked in CHANGED_PSEUDOS.   

References BITMAP_ALLOC, BITMAP_FREE, bitmap_set_range(), CALL_INSN_FUNCTION_USAGE, CALL_P, ext_dce_process_sets(), ext_dce_process_uses(), FAKE_CALL_P, find_reg_note(), FOR_BB_INSNS_REVERSE, global_regs, HARD_FRAME_POINTER_IS_FRAME_POINTER, HARD_FRAME_POINTER_REGNUM, i, JUMP_P, livenow, NONDEBUG_INSN_P, NULL, NULL_RTX, PATTERN(), and RTL_CONST_CALL_P.

Referenced by ext_dce_rd_transfer_n().

◆ ext_dce_process_sets()

static bool ext_dce_process_sets ( rtx_insn * insn,
rtx obj,
bitmap live_tmp )
static
Clear bits in LIVENOW and set bits in LIVE_TMP for objects
set/clobbered by OBJ contained in INSN.

Conceptually it is always safe to ignore a particular destination
here as that will result in more chunks of data being considered
live.  That's what happens when we "continue" the main loop when
we see something we don't know how to handle such as a vector
mode destination.

The more accurate we are in identifying what objects (and chunks
within an object) are set by INSN, the more aggressive the
optimization phase during use handling will be.   

References bitmap_bit_p, bitmap_clear_range(), bitmap_empty_p(), bitmap_set_bit, CALL_P, CONST_INT_P, end(), exact_log2(), FOR_EACH_SUBRTX, gcc_assert, gcc_unreachable, GET_CODE, GET_MODE, GET_MODE_BITSIZE(), GET_MODE_INNER, GET_MODE_MASK, GET_MODE_SIZE(), group_limit(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_UC, i, is_a(), livenow, make_reg_live(), MEM_P, NULL_RTX, paradoxical_subreg_p(), pc_rtx, REG_P, REGNO, SET, SET_DEST, SUBREG_BYTE, subreg_lsb(), SUBREG_P, SUBREG_REG, poly_int< N, C >::to_constant(), UNSPEC_P, and XEXP.

Referenced by ext_dce_process_bb().

◆ ext_dce_process_uses()

static void ext_dce_process_uses ( rtx_insn * insn,
rtx obj,
bitmap live_tmp,
bool skipped_dest )
static
Process uses in INSN contained in OBJ.  Set appropriate bits in LIVENOW
for any chunks of pseudos that become live, potentially filtering using
bits from LIVE_TMP.

If MODIFY is true, then optimize sign/zero extensions to SUBREGs when
the extended bits are never read and mark pseudos which had extensions
eliminated in CHANGED_PSEUDOS.   

References BINARY_P, binop_implies_op2_fully_live(), bitmap_bit_p, bitmap_set_bit, bitmap_set_range(), carry_backpropagate(), CONSTANT_P, ext_dce_try_optimize_insn(), FOR_EACH_SUBRTX_VAR, GET_CODE, GET_MODE, GET_MODE_BITSIZE(), GET_MODE_INNER, GET_MODE_MASK, group_limit(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_UC, i, livenow, modify, NULL_RTX, paradoxical_subreg_p(), pc_rtx, REG_P, REGNO, safe_for_live_propagation(), SET, SET_DEST, SET_SRC, SUBREG_BYTE, subreg_lowpart_p(), subreg_lsb(), SUBREG_P, SUBREG_PROMOTED_SIGNED_P, SUBREG_PROMOTED_UNSIGNED_P, SUBREG_PROMOTED_VAR_P, SUBREG_REG, poly_int< N, C >::to_constant(), XEXP, and y.

Referenced by ext_dce_process_bb().

◆ ext_dce_rd_confluence_n()

static bool ext_dce_rd_confluence_n ( edge )
static
Dummy function for the df_simple_dataflow API.   

Referenced by ext_dce_execute().

◆ ext_dce_rd_transfer_n()

static bool ext_dce_rd_transfer_n ( int bb_index)
static
Process block number BB_INDEX as part of the backward
simple dataflow analysis.  Return TRUE if something in
this block changed or FALSE otherwise.   

References BASIC_BLOCK_FOR_FN, bitmap_clear(), bitmap_copy(), bitmap_equal_p(), bitmap_ior_into(), cfun, ENTRY_BLOCK, EXIT_BLOCK, ext_dce_process_bb(), FOR_EACH_EDGE, livein, livenow, and basic_block_def::succs.

Referenced by ext_dce_execute().

◆ ext_dce_try_optimize_insn()

static void ext_dce_try_optimize_insn ( rtx_insn * insn,
rtx set )
static
INSN has a sign/zero extended source inside SET that we will
try to turn into a SUBREG.   

References bitmap_set_bit, changed_pseudos, dbg_cnt(), dump_file, dump_insn_slim(), gcc_assert, GET_CODE, GET_MODE, print_rtl_single(), REG_P, REGNO, SET_DEST, SET_SRC, simplify_gen_subreg(), SUBREG_P, SUBREG_REG, validate_change(), and XEXP.

Referenced by ext_dce_process_uses().

◆ group_limit()

static int group_limit ( const_rtx reg)
static
We consider four bit groups for liveness:
bit 0..7   (least significant byte)
bit 8..15  (second least significant byte)
bit 16..31
bit 32..BITS_PER_WORD-1   
For the given REG, return the number of bit groups implied by the
size of the REG's mode, up to a maximum of 4 (number of bit groups
tracked by this pass).

For partial integer and variable sized modes also return 4.  This
could possibly be refined for something like PSI mode, but it
does not seem worth the effort.   

References exact_log2(), GET_MODE, GET_MODE_BITSIZE(), GET_MODE_SIZE(), and poly_int< N, C >::to_constant().

Referenced by ext_dce_process_sets(), ext_dce_process_uses(), and make_reg_live().

◆ make_pass_ext_dce()

rtl_opt_pass * make_pass_ext_dce ( gcc::context * ctxt)

◆ make_reg_live()

static void make_reg_live ( bitmap bmap,
int regno )
static
Make all bit groups live for REGNO in bitmap BMAP.  For hard regs,
we assume all groups are live.  For a pseudo we consider the size
of the pseudo to avoid creating unnecessarily live chunks of data.   

References bitmap_set_bit, group_limit(), i, and regno_reg_rtx.

Referenced by ext_dce_init(), and ext_dce_process_sets().

◆ maybe_clear_subreg_promoted_p()

static void maybe_clear_subreg_promoted_p ( void )
static
SUBREG_PROMOTED_VAR_P is set by the gimple->rtl optimizers and
is usually helpful.  However, in some cases setting the value when
it not strictly needed can cause this pass to miss optimizations.

Specifically consider (set (mem) (subreg (reg))).  If set in that
case it will cause more bit groups to be live for REG than would
be strictly necessary which in turn can inhibit extension removal.

So do a pass over the IL wiping the SUBREG_PROMOTED_VAR_P when it
is obviously not needed.   

References get_insns(), GET_MODE, MEM_P, NEXT_INSN(), NONDEBUG_INSN_P, SET_DEST, SET_SRC, single_set(), SUBREG_P, SUBREG_PROMOTED_VAR_P, and SUBREG_REG.

Referenced by ext_dce_execute().

◆ reset_subreg_promoted_p()

static void reset_subreg_promoted_p ( void )
static
We optimize away sign/zero extensions in this pass and replace
them with SUBREGs indicating certain bits are don't cares.

This changes the SUBREG_PROMOTED_VAR_P state of the object.
It is fairly painful to fix this on the fly, so we have
recorded which pseudos are affected and we look for SUBREGs
of those pseudos and fix them up.   

References bitmap_bit_p, changed_pseudos, FOR_EACH_SUBRTX_VAR, GET_CODE, get_insns(), NEXT_INSN(), NONDEBUG_INSN_P, PATTERN(), REG_P, REGNO, SUBREG_PROMOTED_VAR_P, and SUBREG_REG.

Referenced by ext_dce_execute().

◆ safe_for_live_propagation()

static bool safe_for_live_propagation ( rtx_code code)
static
If we know the destination of CODE only uses some low bits
(say just the QI bits of an SI operation), then return true
if we can propagate the need for just the subset of bits
from the destination to the sources.

FIXME: This is safe for operands 1 and 2 of an IF_THEN_ELSE, but not
operand 0.  Thus is likely would need some special casing to handle.   

References GET_RTX_CLASS, RTX_COMM_COMPARE, RTX_COMPARE, RTX_CONST_OBJ, RTX_OBJ, and RTX_TERNARY.

Referenced by ext_dce_process_uses().

Variable Documentation

◆ all_blocks

bitmap all_blocks
static

◆ changed_pseudos

◆ livein

vec<bitmap_head> livein
static
RTL dead zero/sign extension (code) elimination.
   Copyright (C) 2000-2022 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/>.   
These should probably move into a C++ class.   

Referenced by ext_dce_finish(), ext_dce_init(), ext_dce_rd_transfer_n(), and virtual_operand_live::get_live_in().

◆ livenow

◆ modify