From 4ab74a01477d4089a3474d52479ed372c9b5ae29 Mon Sep 17 00:00:00 2001 From: Vladimir Makarov Date: Fri, 14 Nov 2014 20:06:11 +0000 Subject: [PATCH] lra-int.h (lra_create_live_ranges): Add parameter. 2014-11-14 Vladimir Makarov * lra-int.h (lra_create_live_ranges): Add parameter. * lra-lives.c (temp_bitmap): Move higher. (initiate_live_solver): Move temp_bitmap initialization into lra_live_ranges_init. (finish_live_solver): Move temp_bitmap clearing into live_ranges_finish. (process_bb_lives): Add parameter. Use it to control live info update and dead insn elimination. Pass it to mark_regno_live and mark_regno_dead. (lra_create_live_ranges): Add parameter. Pass it to process_bb_lives. (lra_live_ranges_init, lra_live_ranges_finish): See changes in initiate_live_solver and finish_live_solver. * lra-remat.c (do_remat): Process insn non-operand hard regs too. Use temp_bitmap to update avail_cands. * lra.c (lra): Pass new parameter to lra_create_live_ranges. Move check with lra_need_for_spill_p after live range pass. Switch on rematerialization pass. From-SVN: r217588 --- gcc/ChangeLog | 21 ++++++++++++ gcc/lra-int.h | 2 +- gcc/lra-lives.c | 88 +++++++++++++++++++++++++++---------------------- gcc/lra-remat.c | 31 +++++++++++++++-- gcc/lra.c | 23 ++++++++----- 5 files changed, 113 insertions(+), 52 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c42a532a222..54610b69667 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2014-11-14 Vladimir Makarov + + * lra-int.h (lra_create_live_ranges): Add parameter. + * lra-lives.c (temp_bitmap): Move higher. + (initiate_live_solver): Move temp_bitmap initialization into + lra_live_ranges_init. + (finish_live_solver): Move temp_bitmap clearing into + live_ranges_finish. + (process_bb_lives): Add parameter. Use it to control live info + update and dead insn elimination. Pass it to mark_regno_live and + mark_regno_dead. + (lra_create_live_ranges): Add parameter. Pass it to + process_bb_lives. + (lra_live_ranges_init, lra_live_ranges_finish): See changes in + initiate_live_solver and finish_live_solver. + * lra-remat.c (do_remat): Process insn non-operand hard regs too. + Use temp_bitmap to update avail_cands. + * lra.c (lra): Pass new parameter to lra_create_live_ranges. Move + check with lra_need_for_spill_p after live range pass. Switch on + rematerialization pass. + 2014-11-14 Martin Jambor * ipa-prop.h (ipa_get_jf_pass_through_type_preserved): use diff --git a/gcc/lra-int.h b/gcc/lra-int.h index 92dc40cb7da..9422afcbe55 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -353,7 +353,7 @@ extern int *lra_point_freq; extern int lra_hard_reg_usage[FIRST_PSEUDO_REGISTER]; extern int lra_live_range_iter; -extern void lra_create_live_ranges (bool); +extern void lra_create_live_ranges (bool, bool); extern lra_live_range_t lra_copy_live_range_list (lra_live_range_t); extern lra_live_range_t lra_merge_live_ranges (lra_live_range_t, lra_live_range_t); diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c index 9d1c189786b..5868be86e37 100644 --- a/gcc/lra-lives.c +++ b/gcc/lra-lives.c @@ -100,6 +100,9 @@ static sparseset start_living, start_dying; insn. */ static sparseset unused_set, dead_set; +/* Bitmap used for holding intermediate bitmap operation results. */ +static bitmap_head temp_bitmap; + /* Pool for pseudo live ranges. */ static alloc_pool live_range_pool; @@ -420,9 +423,6 @@ get_bb_data_by_index (int index) /* Bitmap with all hard regs. */ static bitmap_head all_hard_regs_bitmap; -/* Bitmap used for holding intermediate bitmap operation results. */ -static bitmap_head temp_bitmap; - /* The transfer function used by the DF equation solver to propagate live info through block with BB_INDEX according to the following equation: @@ -476,7 +476,6 @@ static bitmap_head all_blocks; static void initiate_live_solver (void) { - bitmap_initialize (&temp_bitmap, ®_obstack); bitmap_initialize (&all_hard_regs_bitmap, ®_obstack); bitmap_set_range (&all_hard_regs_bitmap, 0, FIRST_PSEUDO_REGISTER); bb_data = XNEWVEC (struct bb_data_pseudos, last_basic_block_for_fn (cfun)); @@ -508,7 +507,6 @@ finish_live_solver (void) } free (bb_data); bitmap_clear (&all_hard_regs_bitmap); - bitmap_clear (&temp_bitmap); } @@ -640,10 +638,11 @@ check_pseudos_live_through_calls (int regno) backward scan of BB insns. CURR_POINT is the program point where BB ends. The function updates this counter and returns in CURR_POINT the program point where BB starts. The function also - can delete the dead insns. It returns true if pseudo live info was + does local live info updates and can delete the dead insns if + GLOBAL_LIVE_INFO_P. It returns true if pseudo live info was changed at the BB start. */ static bool -process_bb_lives (basic_block bb, int &curr_point) +process_bb_lives (basic_block bb, int &curr_point, bool global_live_info_p) { int i, regno, freq; unsigned int j; @@ -663,11 +662,13 @@ process_bb_lives (basic_block bb, int &curr_point) EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi) mark_pseudo_live (j, curr_point); - bb_gen_pseudos = &get_bb_data (bb)->gen_pseudos; - bb_killed_pseudos = &get_bb_data (bb)->killed_pseudos; - bitmap_clear (bb_gen_pseudos); - bitmap_clear (bb_killed_pseudos); - + if (global_live_info_p) + { + bb_gen_pseudos = &get_bb_data (bb)->gen_pseudos; + bb_killed_pseudos = &get_bb_data (bb)->killed_pseudos; + bitmap_clear (bb_gen_pseudos); + bitmap_clear (bb_killed_pseudos); + } freq = REG_FREQ_FROM_BB (bb); if (lra_dump_file != NULL) @@ -700,7 +701,7 @@ process_bb_lives (basic_block bb, int &curr_point) set = single_set (curr_insn); - if (set != NULL_RTX + if (global_live_info_p && set != NULL_RTX && REG_P (SET_DEST (set)) && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER && find_reg_note (curr_insn, REG_EH_REGION, NULL_RTX) == NULL_RTX && ! may_trap_p (PATTERN (curr_insn)) @@ -736,8 +737,8 @@ process_bb_lives (basic_block bb, int &curr_point) unsigned int uid; rtx_insn *insn; - EXECUTE_IF_SET_IN_BITMAP - (&lra_reg_info[dst_regno].insn_bitmap, 0, uid, bi) + bitmap_copy (&temp_bitmap, &lra_reg_info[dst_regno].insn_bitmap); + EXECUTE_IF_SET_IN_BITMAP (&temp_bitmap, 0, uid, bi) { insn = lra_insn_recog_data[uid]->insn; lra_substitute_pseudo_within_insn (insn, dst_regno, @@ -815,9 +816,9 @@ process_bb_lives (basic_block bb, int &curr_point) for (reg = curr_id->regs; reg != NULL; reg = reg->next) if (reg->type != OP_IN) { - need_curr_point_incr |= mark_regno_live (reg->regno, - reg->biggest_mode, - curr_point, true); + need_curr_point_incr + |= mark_regno_live (reg->regno, reg->biggest_mode, + curr_point, global_live_info_p); check_pseudos_live_through_calls (reg->regno); } @@ -832,9 +833,9 @@ process_bb_lives (basic_block bb, int &curr_point) /* See which defined values die here. */ for (reg = curr_id->regs; reg != NULL; reg = reg->next) if (reg->type == OP_OUT && ! reg->early_clobber && ! reg->subreg_p) - need_curr_point_incr |= mark_regno_dead (reg->regno, - reg->biggest_mode, - curr_point, true); + need_curr_point_incr + |= mark_regno_dead (reg->regno, reg->biggest_mode, + curr_point, global_live_info_p); for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) if (reg->type == OP_OUT && ! reg->early_clobber && ! reg->subreg_p) @@ -874,9 +875,9 @@ process_bb_lives (basic_block bb, int &curr_point) for (reg = curr_id->regs; reg != NULL; reg = reg->next) if (reg->type == OP_IN) { - need_curr_point_incr |= mark_regno_live (reg->regno, - reg->biggest_mode, - curr_point, true); + need_curr_point_incr + |= mark_regno_live (reg->regno, reg->biggest_mode, + curr_point, global_live_info_p); check_pseudos_live_through_calls (reg->regno); } @@ -894,9 +895,9 @@ process_bb_lives (basic_block bb, int &curr_point) /* Mark early clobber outputs dead. */ for (reg = curr_id->regs; reg != NULL; reg = reg->next) if (reg->type == OP_OUT && reg->early_clobber && ! reg->subreg_p) - need_curr_point_incr |= mark_regno_dead (reg->regno, - reg->biggest_mode, - curr_point, true); + need_curr_point_incr + |= mark_regno_dead (reg->regno, reg->biggest_mode, + curr_point, global_live_info_p); for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) if (reg->type == OP_OUT && reg->early_clobber && ! reg->subreg_p) @@ -969,19 +970,25 @@ process_bb_lives (basic_block bb, int &curr_point) make_hard_regno_born (px); } - /* Check if bb border live info was changed. */ - unsigned int live_pseudos_num = 0; bool live_change_p = false; - EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), FIRST_PSEUDO_REGISTER, j, bi) + if (global_live_info_p) { - live_pseudos_num++; - if (! sparseset_bit_p (pseudos_live, j)) + /* Check if bb border live info was changed. */ + unsigned int live_pseudos_num = 0; + EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), + FIRST_PSEUDO_REGISTER, j, bi) { - live_change_p = TRUE; - break; + live_pseudos_num++; + if (! sparseset_bit_p (pseudos_live, j)) + { + live_change_p = TRUE; + break; + } } + live_change_p + = (live_change_p + || sparseset_cardinality (pseudos_live) != live_pseudos_num); } - live_change_p = live_change_p || sparseset_cardinality (pseudos_live) != live_pseudos_num; /* See if we'll need an increment at the end of this basic block. An increment is needed if the PSEUDOS_LIVE set is not empty, @@ -1175,10 +1182,11 @@ int lra_live_range_iter; /* The main entry function creates live ranges only for memory pseudos (or for all ones if ALL_P), set up CONFLICT_HARD_REGS for the - pseudos. It also does global live analysis only for pseudos and - only if the pseudo live info was changed on a BB border. */ + pseudos. It also does dead insn elimination and global live + analysis only for pseudos and only if GLOBAL_LIVE_INFO_P and the + pseudo live info was changed on a BB border. */ void -lra_create_live_ranges (bool all_p) +lra_create_live_ranges (bool all_p, bool global_live_info_p) { basic_block bb; int i, hard_regno, max_regno = max_reg_num (); @@ -1254,7 +1262,7 @@ lra_create_live_ranges (bool all_p) if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun) || bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)) continue; - if (process_bb_lives (bb, curr_point)) + if (process_bb_lives (bb, curr_point, global_live_info_p)) bb_live_change_p = true; } if (bb_live_change_p) @@ -1328,6 +1336,7 @@ lra_live_ranges_init (void) { live_range_pool = create_alloc_pool ("live ranges", sizeof (struct lra_live_range), 100); + bitmap_initialize (&temp_bitmap, ®_obstack); initiate_live_solver (); } @@ -1336,5 +1345,6 @@ void lra_live_ranges_finish (void) { finish_live_solver (); + bitmap_clear (&temp_bitmap); free_alloc_pool (live_range_pool); } diff --git a/gcc/lra-remat.c b/gcc/lra-remat.c index 51a94caf162..f638a1d8740 100644 --- a/gcc/lra-remat.c +++ b/gcc/lra-remat.c @@ -1026,6 +1026,7 @@ do_remat (void) continue; lra_insn_recog_data_t id = lra_get_insn_recog_data (insn); + struct lra_static_insn_data *static_id = id->insn_static_data; struct lra_insn_reg *reg; cand_t cand; unsigned int cid; @@ -1059,7 +1060,10 @@ do_remat (void) HOST_WIDE_INT cand_sp_offset = 0; if (cand != NULL) { - lra_insn_recog_data_t cand_id = lra_get_insn_recog_data (cand->insn); + lra_insn_recog_data_t cand_id + = lra_get_insn_recog_data (cand->insn); + struct lra_static_insn_data *static_cand_id + = cand_id->insn_static_data; rtx saved_op = *cand_id->operand_loc[cand->nop]; /* Check clobbers do not kill something living. */ @@ -1078,6 +1082,16 @@ do_remat (void) break; } + if (reg == NULL) + { + for (reg = static_cand_id->hard_regs; + reg != NULL; + reg = reg->next) + if (reg->type != OP_IN + && TEST_HARD_REG_BIT (live_hard_regs, reg->regno)) + break; + } + if (reg == NULL) { *cand_id->operand_loc[cand->nop] = SET_DEST (set); @@ -1100,6 +1114,7 @@ do_remat (void) } } + bitmap_clear (&temp_bitmap); /* Update avail_cands (see analogous code for calculate_gen_cands). */ for (reg = id->regs; reg != NULL; reg = reg->next) @@ -1115,7 +1130,7 @@ do_remat (void) continue; if (cand->regno == reg->regno || input_regno_present_p (cand->insn, reg->regno)) - bitmap_clear_bit (&avail_cands, cand->index); + bitmap_set_bit (&temp_bitmap, cand->index); } if (CALL_P (insn)) @@ -1124,9 +1139,10 @@ do_remat (void) cand = all_cands[cid]; if (call_used_input_regno_present_p (cand->insn)) - bitmap_clear_bit (&avail_cands, cand->index); + bitmap_set_bit (&temp_bitmap, cand->index); } + bitmap_and_compl_into (&avail_cands, &temp_bitmap); if ((cand = insn_to_cand[INSN_UID (insn)]) != NULL) bitmap_set_bit (&avail_cands, cand->index); @@ -1160,6 +1176,15 @@ do_remat (void) for (i = 0; i < nregs; i++) SET_HARD_REG_BIT (live_hard_regs, hard_regno + i); } + /* Process also hard regs (e.g. CC register) which are part + of insn definition. */ + for (reg = static_id->hard_regs; reg != NULL; reg = reg->next) + if (reg->type == OP_IN + && find_regno_note (insn, REG_DEAD, reg->regno) != NULL) + CLEAR_HARD_REG_BIT (live_hard_regs, reg->regno); + else if (reg->type != OP_IN + && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL) + SET_HARD_REG_BIT (live_hard_regs, reg->regno); } } bitmap_clear (&avail_cands); diff --git a/gcc/lra.c b/gcc/lra.c index 6b99d5bc3d0..9309d5e44c2 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -2296,14 +2296,17 @@ lra (FILE *f) /* As a side-effect of lra_create_live_ranges, we calculate actual_call_used_reg_set, which is needed during lra_inheritance. */ - lra_create_live_ranges (true); + lra_create_live_ranges (true, true); } lra_inheritance (); } if (live_p) lra_clear_live_ranges (); - /* We need live ranges for lra_assign -- so build them. */ - lra_create_live_ranges (true); + /* We need live ranges for lra_assign -- so build them. But + don't remove dead insns or change global live info as we + can undo inheritance transformations after inheritance + pseudo assigning. */ + lra_create_live_ranges (true, false); live_p = true; /* If we don't spill non-reload and non-inheritance pseudos, there is no sense to run memory-memory move coalescing. @@ -2322,7 +2325,7 @@ lra (FILE *f) { if (! live_p) { - lra_create_live_ranges (true); + lra_create_live_ranges (true, true); live_p = true; } if (lra_coalesce ()) @@ -2338,21 +2341,23 @@ lra (FILE *f) bitmap_clear (&lra_subreg_reload_pseudos); bitmap_clear (&lra_inheritance_pseudos); bitmap_clear (&lra_split_regs); - if (! lra_need_for_spills_p ()) - break; if (! live_p) { /* We need full live info for spilling pseudos into registers instead of memory. */ - lra_create_live_ranges (lra_reg_spill_p); + lra_create_live_ranges (lra_reg_spill_p, true); live_p = true; } + /* We should check necessity for spilling here as the above live + range pass can remove spilled pseudos. */ + if (! lra_need_for_spills_p ()) + break; /* Now we know what pseudos should be spilled. Try to rematerialize them first. */ - if (0 && lra_remat ()) + if (lra_remat ()) { /* We need full live info -- see the comment above. */ - lra_create_live_ranges (lra_reg_spill_p); + lra_create_live_ranges (lra_reg_spill_p, true); live_p = true; if (! lra_need_for_spills_p ()) break; -- 2.30.2