Fix liveness analysis in lra for spilled-into hard regs 2017-12-12 Tom de Vries PR rtl-optimization/83327 * lra-int.h (hard_regs_spilled_into): Declare. * lra.c (hard_regs_spilled_into): Define. (init_reg_info): Init hard_regs_spilled_into. * lra-spills.c (assign_spill_hard_regs): Update hard_regs_spilled_into. * lra-lives.c (make_hard_regno_born, make_hard_regno_dead) (process_bb_lives): Handle hard_regs_spilled_into. (lra_create_live_ranges_1): Before doing liveness propagation, clear regs in all_hard_regs_bitmap if set in hard_regs_spilled_into. --- gcc/lra-int.h | 2 ++ gcc/lra-lives.c | 28 ++++++++++++++++++++++++++-- gcc/lra-spills.c | 2 ++ gcc/lra.c | 3 +++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/gcc/lra-int.h b/gcc/lra-int.h index 5a519b0..064961a 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -122,6 +122,8 @@ struct lra_reg /* References to the common info about each register. */ extern struct lra_reg *lra_reg_info; +extern HARD_REG_SET hard_regs_spilled_into; + /* Static info about each insn operand (common for all insns with the same ICODE). Warning: if the structure definition is changed, the initializer for debug_operand_data in lra.c should be changed diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c index 03dfec2..85da626 100644 --- a/gcc/lra-lives.c +++ b/gcc/lra-lives.c @@ -245,7 +245,7 @@ make_hard_regno_born (int regno, bool check_pic_pseudo_p ATTRIBUTE_UNUSED) || i != REGNO (pic_offset_table_rtx)) #endif SET_HARD_REG_BIT (lra_reg_info[i].conflict_hard_regs, regno); - if (fixed_regs[regno]) + if (fixed_regs[regno] || TEST_HARD_REG_BIT (hard_regs_spilled_into, regno)) bitmap_set_bit (bb_gen_pseudos, regno); } @@ -259,7 +259,7 @@ make_hard_regno_dead (int regno) return; sparseset_set_bit (start_dying, regno); CLEAR_HARD_REG_BIT (hard_regs_live, regno); - if (fixed_regs[regno]) + if (fixed_regs[regno] || TEST_HARD_REG_BIT (hard_regs_spilled_into, regno)) { bitmap_clear_bit (bb_gen_pseudos, regno); bitmap_set_bit (bb_killed_pseudos, regno); @@ -1051,6 +1051,25 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) check_pseudos_live_through_calls (j, last_call_used_reg_set); } + for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + { + if (!TEST_HARD_REG_BIT (hard_regs_live, i)) + continue; + + if (!TEST_HARD_REG_BIT (hard_regs_spilled_into, i)) + continue; + + if (bitmap_bit_p (df_get_live_in (bb), i)) + continue; + + live_change_p = true; + if (lra_dump_file) + fprintf (lra_dump_file, + " hard reg r%d is added to live at bb%d start\n", i, + bb->index); + bitmap_set_bit (df_get_live_in (bb), i); + } + if (need_curr_point_incr) next_program_point (curr_point, freq); @@ -1320,6 +1339,11 @@ lra_create_live_ranges_1 (bool all_p, bool dead_insn_p) } /* As we did not change CFG since LRA start we can use DF-infrastructure solver to solve live data flow problem. */ + for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + { + if (TEST_HARD_REG_BIT (hard_regs_spilled_into, i)) + bitmap_clear_bit (&all_hard_regs_bitmap, i); + } df_simple_dataflow (DF_BACKWARD, NULL, live_con_fun_0, live_con_fun_n, live_trans_fun, &all_blocks, diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c index af11b3d..ab13b21 100644 --- a/gcc/lra-spills.c +++ b/gcc/lra-spills.c @@ -291,6 +291,8 @@ assign_spill_hard_regs (int *pseudo_regnos, int n) } if (lra_dump_file != NULL) fprintf (lra_dump_file, " Spill r%d into hr%d\n", regno, hard_regno); + add_to_hard_reg_set (&hard_regs_spilled_into, + lra_reg_info[regno].biggest_mode, hard_regno); /* Update reserved_hard_regs. */ for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next) for (p = r->start; p <= r->finish; p++) diff --git a/gcc/lra.c b/gcc/lra.c index fec2383..047e64f 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -1270,6 +1270,8 @@ static int reg_info_size; /* Common info about each register. */ struct lra_reg *lra_reg_info; +HARD_REG_SET hard_regs_spilled_into; + /* Last register value. */ static int last_reg_value; @@ -1319,6 +1321,7 @@ init_reg_info (void) for (i = 0; i < reg_info_size; i++) initialize_lra_reg_info_element (i); copy_vec.truncate (0); + CLEAR_HARD_REG_SET (hard_regs_spilled_into); }