diff options
Diffstat (limited to 'gcc/regmove.c')
-rw-r--r-- | gcc/regmove.c | 224 |
1 files changed, 15 insertions, 209 deletions
diff --git a/gcc/regmove.c b/gcc/regmove.c index 2a638197a7a..8ce0ea00da7 100644 --- a/gcc/regmove.c +++ b/gcc/regmove.c @@ -58,10 +58,6 @@ struct match { int early_clobber[MAX_RECOG_OPERANDS]; }; -static rtx discover_flags_reg (void); -static void mark_flags_life_zones (rtx); -static void flags_set_1 (rtx, const_rtx, void *); - static int find_matches (rtx, struct match *); static int regclass_compatible_p (int, int); static int fixup_match_2 (rtx, rtx, rtx, rtx); @@ -79,171 +75,6 @@ regclass_compatible_p (int class0, int class1) } -/* Determine if the pattern generated by add_optab has a clobber, - such as might be issued for a flags hard register. To make the - code elsewhere simpler, we handle cc0 in this same framework. - - Return the register if one was discovered. Return NULL_RTX if - if no flags were found. Return pc_rtx if we got confused. */ - -static rtx -discover_flags_reg (void) -{ - rtx tmp; - tmp = gen_rtx_REG (word_mode, 10000); - tmp = gen_add3_insn (tmp, tmp, const2_rtx); - - /* If we get something that isn't a simple set, or a - [(set ..) (clobber ..)], this whole function will go wrong. */ - if (GET_CODE (tmp) == SET) - return NULL_RTX; - else if (GET_CODE (tmp) == PARALLEL) - { - int found; - - if (XVECLEN (tmp, 0) != 2) - return pc_rtx; - tmp = XVECEXP (tmp, 0, 1); - if (GET_CODE (tmp) != CLOBBER) - return pc_rtx; - tmp = XEXP (tmp, 0); - - /* Don't do anything foolish if the md wanted to clobber a - scratch or something. We only care about hard regs. - Moreover we don't like the notion of subregs of hard regs. */ - if (GET_CODE (tmp) == SUBREG - && REG_P (SUBREG_REG (tmp)) - && REGNO (SUBREG_REG (tmp)) < FIRST_PSEUDO_REGISTER) - return pc_rtx; - found = (REG_P (tmp) && REGNO (tmp) < FIRST_PSEUDO_REGISTER); - - return (found ? tmp : NULL_RTX); - } - - return pc_rtx; -} - -/* It is a tedious task identifying when the flags register is live and - when it is safe to optimize. Since we process the instruction stream - multiple times, locate and record these live zones by marking the - mode of the instructions -- - - QImode is used on the instruction at which the flags becomes live. - - HImode is used within the range (exclusive) that the flags are - live. Thus the user of the flags is not marked. - - All other instructions are cleared to VOIDmode. */ - -/* Used to communicate with flags_set_1. */ -static rtx flags_set_1_rtx; -static int flags_set_1_set; - -static void -mark_flags_life_zones (rtx flags) -{ - int flags_regno; - int flags_nregs; - basic_block block; - -#ifdef HAVE_cc0 - /* If we found a flags register on a cc0 host, bail. */ - if (flags == NULL_RTX) - flags = cc0_rtx; - else if (flags != cc0_rtx) - flags = pc_rtx; -#endif - - /* Simple cases first: if no flags, clear all modes. If confusing, - mark the entire function as being in a flags shadow. */ - if (flags == NULL_RTX || flags == pc_rtx) - { - enum machine_mode mode = (flags ? HImode : VOIDmode); - rtx insn; - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - PUT_MODE (insn, mode); - return; - } - -#ifdef HAVE_cc0 - flags_regno = -1; - flags_nregs = 1; -#else - flags_regno = REGNO (flags); - flags_nregs = hard_regno_nregs[flags_regno][GET_MODE (flags)]; -#endif - flags_set_1_rtx = flags; - - /* Process each basic block. */ - FOR_EACH_BB_REVERSE (block) - { - rtx insn, end; - int live; - - insn = BB_HEAD (block); - end = BB_END (block); - - /* Look out for the (unlikely) case of flags being live across - basic block boundaries. */ - live = 0; -#ifndef HAVE_cc0 - { - int i; - for (i = 0; i < flags_nregs; ++i) - live |= REGNO_REG_SET_P (df_get_live_in (block), flags_regno + i); - } -#endif - - while (1) - { - /* Process liveness in reverse order of importance -- - alive, death, birth. This lets more important info - overwrite the mode of lesser info. */ - - if (INSN_P (insn)) - { -#ifdef HAVE_cc0 - /* In the cc0 case, death is not marked in reg notes, - but is instead the mere use of cc0 when it is alive. */ - if (live && reg_mentioned_p (cc0_rtx, PATTERN (insn))) - live = 0; -#else - /* In the hard reg case, we watch death notes. */ - if (live && find_regno_note (insn, REG_DEAD, flags_regno)) - live = 0; -#endif - PUT_MODE (insn, (live ? HImode : VOIDmode)); - - /* In either case, birth is denoted simply by its presence - as the destination of a set. */ - flags_set_1_set = 0; - note_stores (PATTERN (insn), flags_set_1, NULL); - if (flags_set_1_set) - { - live = 1; - PUT_MODE (insn, QImode); - } - } - else - PUT_MODE (insn, (live ? HImode : VOIDmode)); - - if (insn == end) - break; - insn = NEXT_INSN (insn); - } - } -} - -/* A subroutine of mark_flags_life_zones, called through note_stores. */ - -static void -flags_set_1 (rtx x, const_rtx pat, void *data ATTRIBUTE_UNUSED) -{ - if (GET_CODE (pat) == SET - && reg_overlap_mentioned_p (x, flags_set_1_rtx)) - flags_set_1_set = 1; -} - #ifdef AUTO_INC_DEC /* Find the place in the rtx X where REG is used as a memory address. @@ -1051,25 +882,21 @@ fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset) return 0; } -/* Main entry for the register move optimization. - F is the first instruction. - NREGS is one plus the highest pseudo-reg number used in the instruction. - REGMOVE_DUMP_FILE is a stream for output of a trace of actions taken - (or 0 if none should be output). */ +/* Main entry for the register move optimization. */ -static void -regmove_optimize (rtx f, int nregs) +static unsigned int +regmove_optimize (void) { rtx insn; struct match match; - int pass; int i; rtx copy_src, copy_dst; + int nregs = max_reg_num (); /* ??? Hack. Regmove doesn't examine the CFG, and gets mightily confused by non-call exceptions ending blocks. */ if (flag_non_call_exceptions) - return; + return 0; df_note_add_problem (); df_analyze (); @@ -1077,43 +904,30 @@ regmove_optimize (rtx f, int nregs) regstat_init_n_sets_and_refs (); regstat_compute_ri (); - /* Find out where a potential flags register is live, and so that we - can suppress some optimizations in those zones. */ - mark_flags_life_zones (discover_flags_reg ()); - regno_src_regno = XNEWVEC (int, nregs); for (i = nregs; --i >= 0; ) regno_src_regno[i] = -1; - /* A forward/backward pass. Replace output operands with input operands. */ + /* A forward pass. Replace output operands with input operands. */ - for (pass = 0; pass <= 2; pass++) + if (flag_expensive_optimizations) { - if (! flag_regmove && pass >= flag_expensive_optimizations) - goto done; - if (dump_file) - fprintf (dump_file, "Starting %s pass...\n", - pass ? "backward" : "forward"); + fprintf (dump_file, "Starting forward pass...\n"); - for (insn = pass ? get_last_insn () : f; insn; - insn = pass ? PREV_INSN (insn) : NEXT_INSN (insn)) + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { - rtx set; - - set = single_set (insn); + rtx set = single_set (insn); if (! set) continue; - if (flag_expensive_optimizations && ! pass - && (GET_CODE (SET_SRC (set)) == SIGN_EXTEND - || GET_CODE (SET_SRC (set)) == ZERO_EXTEND) + if ((GET_CODE (SET_SRC (set)) == SIGN_EXTEND + || GET_CODE (SET_SRC (set)) == ZERO_EXTEND) && REG_P (XEXP (SET_SRC (set), 0)) && REG_P (SET_DEST (set))) optimize_reg_copy_3 (insn, SET_DEST (set), SET_SRC (set)); - if (flag_expensive_optimizations && ! pass - && REG_P (SET_SRC (set)) + if (REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))) { /* If this is a register-register copy where SRC is not dead, @@ -1418,7 +1232,6 @@ regmove_optimize (rtx f, int nregs) } } - done: /* Clean up. */ free (regno_src_regno); if (reg_set_in_bb) @@ -1428,6 +1241,7 @@ regmove_optimize (rtx f, int nregs) } regstat_free_n_sets_and_refs (); regstat_free_ri (); + return 0; } /* Returns nonzero if INSN's pattern has matching constraints for any operand. @@ -1529,14 +1343,6 @@ gate_handle_regmove (void) return (optimize > 0 && flag_regmove); } -/* Register allocation pre-pass, to reduce number of moves necessary - for two-address machines. */ -static unsigned int -rest_of_handle_regmove (void) -{ - regmove_optimize (get_insns (), max_reg_num ()); - return 0; -} struct rtl_opt_pass pass_regmove = { @@ -1544,7 +1350,7 @@ struct rtl_opt_pass pass_regmove = RTL_PASS, "regmove", /* name */ gate_handle_regmove, /* gate */ - rest_of_handle_regmove, /* execute */ + regmove_optimize, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ |