diff options
author | Vladimir N. Makarov <vmakarov@redhat.com> | 2020-10-30 15:05:22 -0400 |
---|---|---|
committer | Vladimir N. Makarov <vmakarov@redhat.com> | 2020-10-30 15:08:23 -0400 |
commit | 44fbc9c6e02ca5b8f98f25b514ed7588e7ba733d (patch) | |
tree | cb3a5a5e1fbd03203fd0a2842a6ffca63195bc51 /gcc/ira.c | |
parent | bdf6524bc0bfa0908a7a7c52e799dbecbebaefe8 (diff) | |
download | gcc-44fbc9c6e02ca5b8f98f25b514ed7588e7ba733d.zip gcc-44fbc9c6e02ca5b8f98f25b514ed7588e7ba733d.tar.gz gcc-44fbc9c6e02ca5b8f98f25b514ed7588e7ba733d.tar.bz2 |
Take insn scratch RA requirements into account in IRA.
The patch changes insn scratches which require registers for all
insn alternatives (in other words w/o X constraint in scratch
constraint string). This is done before IRA staring its work. LRA
still continue to change the rest scratches (with X constraint and in
insn created during IRA) into pseudos. As before the patch at the end
of LRA work, spilled scratch pseudos (for which X constraint was
chosen) changed into scratches back.
gcc/ChangeLog:
* lra.c (get_scratch_reg): New function.
(remove_scratches_1): Rename remove_insn_scratches. Use
ira_remove_insn_scratches and get_scratch_reg.
(remove_scratches): Do not
initialize scratches, scratch_bitmap, and scratch_operand_bitmap.
(lra): Call ira_restore_scratches instead of restore_scratches.
(struct sloc, sloc_t, scratches, scratch_bitmap)
(scratch_operand_bitmap, lra_former_scratch_p)
(lra_former_scratch_operand_p, lra_register_new_scratch_op)
(restore_scratches): Move them to ...
* ira.c: ... here.
(former_scratch_p, former_scratch_operand_p): Rename to
ira_former_scratch_p and ira_former_scratch_operand_p.
(contains_X_constraint_p): New function.
(register_new_scratch_op): Rename to ira_register_new_scratch_op.
Change it to work for IRA and LRA.
(restore_scratches): Rename to ira_restore_scratches.
(get_scratch_reg, ira_remove_insn_scratches): New functions.
(ira): Call ira_remove_scratches if we use LRA.
* ira.h (ira_former_scratch_p, ira_former_scratch_operand_p): New
prototypes.
(ira_register_new_scratch_op, ira_restore_scratches): New prototypes.
(ira_remove_insn_scratches): New prototype.
* lra-int.h (lra_former_scratch_p, lra_former_scratch_operand_p):
Remove prototypes.
(lra_register_new_scratch_op): Ditto.
* lra-constraints.c: Rename lra_former_scratch_p and
lra_former_scratch_p to ira_former_scratch_p and to
ira_former_scratch_p.
* lra-remat.c: Ditto.
* lra-spills.c: Rename lra_former_scratch_p to ira_former_scratch_p.
Diffstat (limited to 'gcc/ira.c')
-rw-r--r-- | gcc/ira.c | 217 |
1 files changed, 203 insertions, 14 deletions
@@ -5133,7 +5133,191 @@ move_unallocated_pseudos (void) first_moveable_pseudo = last_moveable_pseudo = 0; } + + + +/* Code dealing with scratches (changing them onto + pseudos and restoring them from the pseudos). + + We change scratches into pseudos at the beginning of IRA to + simplify dealing with them (conflicts, hard register assignments). + + If the pseudo denoting scratch was spilled it means that we do not + need a hard register for it. Such pseudos are transformed back to + scratches at the end of LRA. */ + +/* Description of location of a former scratch operand. */ +struct sloc +{ + rtx_insn *insn; /* Insn where the scratch was. */ + int nop; /* Number of the operand which was a scratch. */ + unsigned regno; /* regno gnerated instead of scratch */ + int icode; /* Original icode from which scratch was removed. */ +}; + +typedef struct sloc *sloc_t; + +/* Locations of the former scratches. */ +static vec<sloc_t> scratches; + +/* Bitmap of scratch regnos. */ +static bitmap_head scratch_bitmap; + +/* Bitmap of scratch operands. */ +static bitmap_head scratch_operand_bitmap; + +/* Return true if pseudo REGNO is made of SCRATCH. */ +bool +ira_former_scratch_p (int regno) +{ + return bitmap_bit_p (&scratch_bitmap, regno); +} + +/* Return true if the operand NOP of INSN is a former scratch. */ +bool +ira_former_scratch_operand_p (rtx_insn *insn, int nop) +{ + return bitmap_bit_p (&scratch_operand_bitmap, + INSN_UID (insn) * MAX_RECOG_OPERANDS + nop) != 0; +} + +/* Register operand NOP in INSN as a former scratch. It will be + changed to scratch back, if it is necessary, at the LRA end. */ +void +ira_register_new_scratch_op (rtx_insn *insn, int nop, int icode) +{ + rtx op = *recog_data.operand_loc[nop]; + sloc_t loc = XNEW (struct sloc); + ira_assert (REG_P (op)); + loc->insn = insn; + loc->nop = nop; + loc->regno = REGNO (op); + loc->icode = icode; + scratches.safe_push (loc); + bitmap_set_bit (&scratch_bitmap, REGNO (op)); + bitmap_set_bit (&scratch_operand_bitmap, + INSN_UID (insn) * MAX_RECOG_OPERANDS + nop); + add_reg_note (insn, REG_UNUSED, op); +} + +/* Return true if string STR contains constraint 'X'. */ +static bool +contains_X_constraint_p (const char *str) +{ + int c; + + while ((c = *str)) + { + str += CONSTRAINT_LEN (c, str); + if (c == 'X') return true; + } + return false; +} + +/* Change INSN's scratches into pseudos and save their location. */ +bool +ira_remove_insn_scratches (rtx_insn *insn, bool all_p, FILE *dump_file, + rtx (*get_reg) (rtx original)) +{ + int i; + bool insn_changed_p; + rtx reg, *loc; + + extract_insn (insn); + insn_changed_p = false; + for (i = 0; i < recog_data.n_operands; i++) + { + loc = recog_data.operand_loc[i]; + if (GET_CODE (*loc) == SCRATCH && GET_MODE (*loc) != VOIDmode) + { + if (! all_p && contains_X_constraint_p (recog_data.constraints[i])) + continue; + insn_changed_p = true; + *loc = reg = get_reg (*loc); + ira_register_new_scratch_op (insn, i, INSN_CODE (insn)); + if (ira_dump_file != NULL) + fprintf (dump_file, + "Removing SCRATCH to p%u in insn #%u (nop %d)\n", + REGNO (reg), INSN_UID (insn), i); + } + } + return insn_changed_p; +} + +/* Return new register of the same mode as ORIGINAL. Used in + ira_remove_scratches. */ +static rtx +get_scratch_reg (rtx original) +{ + return gen_reg_rtx (GET_MODE (original)); +} + +/* Change scratches into pseudos and save their location. */ +void +ira_remove_scratches (void) +{ + basic_block bb; + rtx_insn *insn; + + scratches.create (get_max_uid ()); + bitmap_initialize (&scratch_bitmap, ®_obstack); + bitmap_initialize (&scratch_operand_bitmap, ®_obstack); + FOR_EACH_BB_FN (bb, cfun) + FOR_BB_INSNS (bb, insn) + if (INSN_P (insn) + && ira_remove_insn_scratches (insn, false, ira_dump_file, get_scratch_reg)) + /* Because we might use DF, we need to keep DF info up to date. */ + df_insn_rescan (insn); +} + +/* Changes pseudos created by function remove_scratches onto scratches. */ +void +ira_restore_scratches (FILE *dump_file) +{ + int regno, n; + unsigned i; + rtx *op_loc; + sloc_t loc; + + for (i = 0; scratches.iterate (i, &loc); i++) + { + /* Ignore already deleted insns. */ + if (NOTE_P (loc->insn) + && NOTE_KIND (loc->insn) == NOTE_INSN_DELETED) + continue; + extract_insn (loc->insn); + if (loc->icode != INSN_CODE (loc->insn)) + { + /* The icode doesn't match, which means the insn has been modified + (e.g. register elimination). The scratch cannot be restored. */ + continue; + } + op_loc = recog_data.operand_loc[loc->nop]; + if (REG_P (*op_loc) + && ((regno = REGNO (*op_loc)) >= FIRST_PSEUDO_REGISTER) + && reg_renumber[regno] < 0) + { + /* It should be only case when scratch register with chosen + constraint 'X' did not get memory or hard register. */ + ira_assert (ira_former_scratch_p (regno)); + *op_loc = gen_rtx_SCRATCH (GET_MODE (*op_loc)); + for (n = 0; n < recog_data.n_dups; n++) + *recog_data.dup_loc[n] + = *recog_data.operand_loc[(int) recog_data.dup_num[n]]; + if (dump_file != NULL) + fprintf (dump_file, "Restoring SCRATCH in insn #%u(nop %d)\n", + INSN_UID (loc->insn), loc->nop); + } + } + for (i = 0; scratches.iterate (i, &loc); i++) + free (loc); + scratches.release (); + bitmap_clear (&scratch_bitmap); + bitmap_clear (&scratch_operand_bitmap); +} + + /* If the backend knows where to allocate pseudos for hard register initial values, register these allocations now. */ static void @@ -5182,8 +5366,10 @@ allocate_initial_values (void) &hreg, &preg)); } } + + /* True when we use LRA instead of reload pass for the current function. */ bool ira_use_lra_p; @@ -5204,6 +5390,17 @@ ira (FILE *f) bool saved_flag_caller_saves = flag_caller_saves; enum ira_region saved_flag_ira_region = flag_ira_region; + if (flag_ira_verbose < 10) + { + internal_flag_ira_verbose = flag_ira_verbose; + ira_dump_file = f; + } + else + { + internal_flag_ira_verbose = flag_ira_verbose - 10; + ira_dump_file = stderr; + } + clear_bb_flags (); /* Determine if the current function is a leaf before running IRA @@ -5250,17 +5447,6 @@ ira (FILE *f) if (flag_caller_saves && !ira_use_lra_p) init_caller_save (); - if (flag_ira_verbose < 10) - { - internal_flag_ira_verbose = flag_ira_verbose; - ira_dump_file = f; - } - else - { - internal_flag_ira_verbose = flag_ira_verbose - 10; - ira_dump_file = stderr; - } - setup_prohibited_mode_move_regs (); decrease_live_ranges_number (); df_note_add_problem (); @@ -5305,9 +5491,6 @@ ira (FILE *f) if (warn_clobbered) generate_setjmp_warnings (); - if (resize_reg_info () && flag_ira_loop_pressure) - ira_set_pseudo_classes (true, ira_dump_file); - init_alias_analysis (); loop_optimizer_init (AVOID_CFG_MODIFICATIONS); reg_equiv = XCNEWVEC (struct equivalence, max_reg_num ()); @@ -5331,6 +5514,12 @@ ira (FILE *f) end_alias_analysis (); free (reg_equiv); + if (ira_use_lra_p) + ira_remove_scratches (); + + if (resize_reg_info () && flag_ira_loop_pressure) + ira_set_pseudo_classes (true, ira_dump_file); + setup_reg_equiv (); grow_reg_equivs (); setup_reg_equiv_init (); |