GCC Middle and Back End API 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"
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_pass * | make_pass_ext_dce (gcc::context *ctxt) |
Variables | |
static vec< bitmap_head > | livein |
static bitmap | all_blocks |
static bitmap | livenow |
static bitmap | changed_pseudos |
static bool | modify |
#define UNSPEC_P | ( | X | ) |
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().
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().
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().
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().
|
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().
|
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().
|
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().
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().
|
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().
Dummy function for the df_simple_dataflow API.
Referenced by ext_dce_execute().
|
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().
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().
|
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().
rtl_opt_pass * make_pass_ext_dce | ( | gcc::context * | ctxt | ) |
|
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().
|
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().
|
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().
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().
|
static |
Referenced by ext_dce_execute(), ext_dce_finish(), and ext_dce_init().
|
static |
Referenced by ext_dce_finish(), ext_dce_init(), ext_dce_try_optimize_insn(), improve_inheritance(), and reset_subreg_promoted_p().
|
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().
|
static |
|
static |