Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
- index fa4e083..836e6d1 100644
- --- a/gcc/config/arm/arm.c
- +++ b/gcc/config/arm/arm.c
- @@ -73,6 +73,8 @@
- #include "builtins.h"
- #include "tm-constrs.h"
- #include "rtl-iter.h"
- +#include "tree-pass.h"
- +#include "context.h"
- /* This file should be included last. */
- #include "target-def.h"
- @@ -3397,6 +3399,23 @@ arm_option_override (void)
- /* Init initial mode for testing. */
- thumb_flipper = TARGET_THUMB;
- +
- +
- + /* Registering the pass must be done at start up. It's
- + convenient to do it here. */
- +
- + rtl_opt_pass *make_pass_rtl_remove_temps (gcc::context *);
- +
- + opt_pass *new_pass = make_pass_rtl_remove_temps (g);
- + struct register_pass_info insert_pass_rtl_remove_temps =
- + {
- + new_pass, /* pass */
- + "combine", /* reference_pass_name */
- + 1, /* ref_pass_instance_number */
- + PASS_POS_INSERT_BEFORE /* po_op */
- + };
- + pass_init_dump_file (new_pass);
- + register_pass (&insert_pass_rtl_remove_temps);
- }
- static void
- @@ -29781,4 +29800,284 @@ arm_sched_fusion_priority (rtx_insn *insn, int max_pri,
- *pri = tmp;
- return;
- }
- +
- +/*
- + * The pass tries to fold arm_cmpsi_insn into andsi3_compare0_scratch or
- + * zeroextractsi_compare0_scratch if reg:CC in arm_cmpsi_insn is set from arm_andsi3_insn.
- + */
- +
- +namespace {
- +
- +const pass_data pass_data_rtl_remove_temps =
- +{
- + RTL_PASS, /* type */
- + "remove-temps", /* name */
- + OPTGROUP_NONE, /* optinfo_flags */
- + TV_NONE,
- + PROP_cfglayout, /* properties_required */
- + 0, /* properties_provided */
- + 0, /* properties_destroyed */
- + 0, /* todo_flags_start */
- + TODO_df_finish, /* todo_flags_finish */
- +};
- +
- +class pass_rtl_remove_temps : public rtl_opt_pass
- +{
- +public:
- + pass_rtl_remove_temps (gcc::context *ctxt)
- + : rtl_opt_pass (pass_data_rtl_remove_temps, ctxt)
- + {}
- +
- + /* opt_pass methods: */
- + virtual bool gate (function *);
- + virtual unsigned int execute (function *);
- +
- +private:
- + static rtx_insn *get_def_insn (rtx_insn *, rtx);
- + static bool reg_simode_p (rtx x) { return REG_P (x) && (GET_MODE (x) == SImode); }
- + static rtx fold (rtx, enum rtx_code *);
- + static rtx gen_andsi3_compare0_scratch (rtx, rtx);
- + static rtx gen_zeroextractsi_compare0_scratch (rtx, rtx);
- + static int getlastbitpos(int x);
- + static int getfirstbitpos(int x);
- + static void change_jump_insn (rtx_insn *);
- + static void do_remove_temp (rtx_insn *insn);
- +}; // class pass_rtl_remove_temps
- +
- +
- +int
- +pass_rtl_remove_temps::getfirstbitpos (int x)
- +{
- + if (x == 0)
- + return -1;
- + return floor_log2 (x & (~x + 1));
- +}
- +
- +int
- +pass_rtl_remove_temps::getlastbitpos (int x)
- +{
- + /* FIXME: Rewrite */
- + if (x == 0)
- + return -1;
- +
- + unsigned pos, bitpos=-1;
- + for (pos = 0; x; x >>=1, pos++)
- + if (x & 1)
- + bitpos = pos;
- +
- + return bitpos;
- +}
- +
- +rtx_insn *
- +pass_rtl_remove_temps::get_def_insn (rtx_insn *insn, rtx reg)
- +{
- + df_ref use;
- + struct df_link *ref_chain, *ref_link;
- +
- + use = df_find_use (insn, reg);
- + gcc_assert (use != NULL);
- + ref_chain = DF_REF_CHAIN (use);
- +
- + // Punt if a use has multiple defs
- + if (ref_chain->next)
- + return NULL;
- +
- + if (ref_chain->ref == NULL || DF_REF_INSN_INFO (ref_chain->ref) == NULL)
- + return NULL;
- +
- + rtx_insn *def_insn = DF_REF_INSN (ref_chain->ref);
- +
- + /* Check if def_insn has form
- + (set (reg:SI)
- + (and:SI (reg:SI)
- + (const_int or reg:SI)))
- + */
- +
- + rtx pattern = PATTERN (def_insn);
- + return ((GET_CODE (pattern) == SET)
- + && reg_simode_p (SET_DEST (pattern))
- + && (GET_CODE (SET_SRC (pattern)) == AND)
- + && reg_simode_p (XEXP (SET_SRC (pattern), 0))
- + && (reg_simode_p (XEXP (SET_SRC (pattern), 1))
- + || (GET_CODE (XEXP (SET_SRC (pattern), 1)) == CONST_INT)))
- + ? def_insn
- + : NULL;
- +}
- +
- +rtx
- +pass_rtl_remove_temps::gen_andsi3_compare0_scratch (rtx op0, rtx op1)
- +{
- + if (!s_register_operand (op0, SImode) || !arm_not_operand (op1, SImode))
- + return NULL_RTX;
- +
- + rtx reg = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
- + rtx o0 = gen_rtx_AND (SImode, op0, op1);
- + rtx o1 = GEN_INT (0);
- + rtx compare_expr = gen_rtx_COMPARE (CC_NOOVmode, o0, o1);
- + rtx x = gen_rtx_SET (reg, compare_expr);
- +
- + rtx scratch_expr = gen_rtx_SCRATCH (SImode);
- + rtx clobber_expr = gen_rtx_CLOBBER (VOIDmode, scratch_expr);
- + rtx parallelexpr = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x, clobber_expr));
- +
- + return parallelexpr;
- +}
- +
- +rtx
- +pass_rtl_remove_temps::gen_zeroextractsi_compare0_scratch (rtx op0, rtx op1)
- +{
- + if (!s_register_operand (op0, SImode))
- + return NULL_RTX;
- +
- + int x = INTVAL (op1);
- + unsigned pos = getfirstbitpos (x);
- + unsigned len = (getlastbitpos (x) - pos) + 1;
- +
- + if (!(TARGET_32BIT
- + && pos >= 0 && pos < 32
- + && len > 0
- + && (len + (pos & 1) <= 8)
- + && (len + pos <= 32)))
- + return NULL_RTX;
- +
- + if ((((1 << len) - 1) << pos) != x)
- + return NULL_RTX;
- +
- + rtx zexpr = gen_rtx_ZERO_EXTRACT (SImode, op0, GEN_INT (len), GEN_INT (pos));
- + rtx compare_expr = gen_rtx_COMPARE (CC_NOOVmode, zexpr, GEN_INT (0));
- + rtx reg = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
- + return gen_rtx_SET (reg, compare_expr);
- +}
- +
- +/* we need to change reg:CC 100 in JUMP_INSN to reg:CC_NOOV 100 in
- + (set (pc)
- + (if_then_else (eq/ne (reg:CC 100)
- + (const_int 0))
- + (label-ref)
- + (pc)))
- +*/
- +
- +void
- +pass_rtl_remove_temps::change_jump_insn (rtx_insn *next)
- +{
- + gcc_assert (JUMP_P (next));
- +
- + rtx pat = PATTERN (next);
- + rtx op = SET_SRC (pat);
- + if (GET_CODE (op) == IF_THEN_ELSE)
- + {
- + rtx cond = XEXP (op, 0);
- + if (GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
- + {
- + rtx reg = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
- + XEXP (cond, 0) = reg;
- + df_insn_rescan (next);
- + }
- + }
- +}
- +
- +/* Transform compare-against-0 insn to rtx from either zeroextractsi_compare0_scratch
- + * or andsi3_compare0_scratch.
- + * codep stores ZERO_EXTRACT if we generate from zeroextractsi_compare0_scratch
- + * This is required because if we change this rtx to zeroextractsi_compare0_scratch
- + * reg:CC 100 in jump_insn needs to be changed to reg:CC_NOOV 100, to match the peephole
- + * pattern in thumb2.md:1527
- + */
- +rtx
- +pass_rtl_remove_temps::fold (rtx pat, enum rtx_code *codep)
- +{
- + rtx and_expr = SET_SRC (pat);
- + rtx op0 = XEXP (and_expr, 0);
- + rtx op1 = XEXP (and_expr, 1);
- +
- + if (GET_CODE (op1) == CONST_INT)
- + {
- + rtx x = gen_zeroextractsi_compare0_scratch (op0, op1);
- + if (x != NULL_RTX)
- + {
- + *codep = ZERO_EXTRACT;
- + return x;
- + }
- + }
- +
- + *codep = AND;
- + return gen_andsi3_compare0_scratch (op0, op1);
- +}
- +
- +bool
- +pass_rtl_remove_temps::gate (function *)
- +{
- + return flag_rtl_remove_temps != 0 && optimize > 0;
- +}
- +
- +} // anon namespace
- +
- +void
- +pass_rtl_remove_temps::do_remove_temp (rtx_insn *insn)
- +{
- + /* Check for:
- + (set (reg:cc)
- + (compare:cc (reg:SI)
- + (const_int 0)))
- + */
- +
- + rtx pattern = PATTERN (insn);
- + if (GET_CODE (pattern) == SET
- + && (REG_P (SET_DEST (pattern))) && GET_MODE (SET_DEST (pattern)) == CCmode
- + && (GET_CODE (SET_SRC (pattern)) == COMPARE))
- + {
- + rtx compare_expr = SET_SRC (pattern);
- + rtx op0 = XEXP (compare_expr, 0);
- + rtx op1 = XEXP (compare_expr, 1);
- +
- + if (REG_P (op0) && (GET_MODE (op0) == SImode)
- + && (GET_CODE (op1) == CONST_INT) && (INTVAL (op1) == 0))
- + {
- + rtx_insn *def_insn = pass_rtl_remove_temps::get_def_insn (insn, op0);
- + if (def_insn)
- + {
- + enum rtx_code code = UNKNOWN;
- + rtx x = pass_rtl_remove_temps::fold (PATTERN (def_insn), &code);
- + if (x != NULL_RTX)
- + {
- + rtx_insn *a = emit_insn_before (x, insn);
- + recog_memoized (a);
- + df_insn_rescan (a);
- + if (code == ZERO_EXTRACT)
- + change_jump_insn (NEXT_INSN (insn));
- + delete_insn (insn);
- + }
- + }
- + }
- + }
- +}
- +
- +
- +unsigned int
- +pass_rtl_remove_temps::execute (function *)
- +{
- + df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
- + df_chain_add_problem (DF_UD_CHAIN);
- + df_analyze ();
- + df_set_flags (DF_DEFER_INSN_RESCAN);
- +
- + rtx_insn *next;
- +
- + for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
- + {
- + if (!INSN_P (insn))
- + continue;
- +
- + do_remove_temp (insn);
- + }
- +
- + return 0;
- +}
- +
- +rtl_opt_pass *
- +make_pass_rtl_remove_temps (gcc::context *ctxt)
- +{
- + return new pass_rtl_remove_temps (ctxt);
- +}
- +
- #include "gt-arm.h"
- diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
- index c9095b9..20b1d05 100644
- --- a/gcc/config/arm/arm.opt
- +++ b/gcc/config/arm/arm.opt
- @@ -281,3 +281,7 @@ Assume loading data from flash is slower than fetching instructions.
- masm-syntax-unified
- Target Report Var(inline_asm_unified) Init(0) Save
- Assume unified syntax for Thumb inline assembly code.
- +
- +fremove-temps
- +Target Report Var(flag_rtl_remove_temps) Optimization
- +Fold arm_andsi3_insn/arm_cmpsi_insn to zeroextractsi_compare0_scratch or andsi3_compare0_scratch
Advertisement
Add Comment
Please, Sign In to add comment