diff options
author | Vladimir Makarov <vmakarov@redhat.com> | 2018-03-09 16:00:36 +0000 |
---|---|---|
committer | Vladimir Makarov <vmakarov@gcc.gnu.org> | 2018-03-09 16:00:36 +0000 |
commit | e0cd6bc00966de0a3a77b642f9507d9c83b398f1 (patch) | |
tree | de7bad1e1e9a7a1d01900aa85dc8de1b2e98279f /gcc/lra-constraints.c | |
parent | a4017ff7722614f749a0d5eab315e929b2035e8a (diff) | |
download | gcc-e0cd6bc00966de0a3a77b642f9507d9c83b398f1.zip gcc-e0cd6bc00966de0a3a77b642f9507d9c83b398f1.tar.gz gcc-e0cd6bc00966de0a3a77b642f9507d9c83b398f1.tar.bz2 |
re PR target/83712 ("Unable to find a register to spill" when compiling for thumb1)
2018-03-09 Vladimir Makarov <vmakarov@redhat.com>
PR target/83712
* lra-assigns.c (assign_by_spills): Return a flag of reload
assignment failure. Do not process the reload assignment
failures. Do not spill other reload pseudos if they has the same
reg class.
(lra_assign): Add a return arg. Set up from the result of
assign_by_spills call.
(find_reload_regno_insns, lra_split_hard_reg_for): New functions.
* lra-constraints.c (split_reg): Add a new arg. Use it instead of
usage_insns if it is not NULL.
(spill_hard_reg_in_range): New function.
(split_if_necessary, inherit_in_ebb): Pass a new arg to split_reg.
* lra-int.h (spill_hard_reg_in_range, lra_split_hard_reg_for): New
function prototypes.
(lra_assign): Change prototype.
* lra.c (lra): Add code to deal with fails by splitting hard reg
live ranges.
2018-03-09 Vladimir Makarov <vmakarov@redhat.com>
PR target/83712
* gcc.target/arm/pr83712.c: New.
From-SVN: r258390
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r-- | gcc/lra-constraints.c | 80 |
1 files changed, 59 insertions, 21 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 59b9754..6bfd465 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -5445,7 +5445,8 @@ lra_copy_reg_equiv (unsigned int new_regno, unsigned int original_regno) /* Do split transformations for insn INSN, which defines or uses ORIGINAL_REGNO. NEXT_USAGE_INSNS specifies which instruction in the EBB next uses ORIGINAL_REGNO; it has the same form as the - "insns" field of usage_insns. + "insns" field of usage_insns. If TO is not NULL, we don't use + usage_insns, we put restore insns after TO insn. The transformations look like: @@ -5467,7 +5468,7 @@ lra_copy_reg_equiv (unsigned int new_regno, unsigned int original_regno) transformation. */ static bool split_reg (bool before_p, int original_regno, rtx_insn *insn, - rtx next_usage_insns) + rtx next_usage_insns, rtx_insn *to) { enum reg_class rclass; rtx original_reg; @@ -5600,29 +5601,37 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn, if (!HARD_REGISTER_NUM_P (original_regno) && mode == PSEUDO_REGNO_MODE (original_regno)) lra_copy_reg_equiv (new_regno, original_regno); - after_p = usage_insns[original_regno].after_p; lra_reg_info[new_regno].restore_rtx = regno_reg_rtx[original_regno]; bitmap_set_bit (&check_only_regs, new_regno); bitmap_set_bit (&check_only_regs, original_regno); bitmap_set_bit (&lra_split_regs, new_regno); - for (;;) + if (to != NULL) { - if (GET_CODE (next_usage_insns) != INSN_LIST) - { - usage_insn = next_usage_insns; - break; - } - usage_insn = XEXP (next_usage_insns, 0); - lra_assert (DEBUG_INSN_P (usage_insn)); - next_usage_insns = XEXP (next_usage_insns, 1); - lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false, - true); - lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn)); - if (lra_dump_file != NULL) + usage_insn = to; + after_p = TRUE; + } + else + { + after_p = usage_insns[original_regno].after_p; + for (;;) { - fprintf (lra_dump_file, " Split reuse change %d->%d:\n", - original_regno, new_regno); - dump_insn_slim (lra_dump_file, as_a <rtx_insn *> (usage_insn)); + if (GET_CODE (next_usage_insns) != INSN_LIST) + { + usage_insn = next_usage_insns; + break; + } + usage_insn = XEXP (next_usage_insns, 0); + lra_assert (DEBUG_INSN_P (usage_insn)); + next_usage_insns = XEXP (next_usage_insns, 1); + lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false, + true); + lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn)); + if (lra_dump_file != NULL) + { + fprintf (lra_dump_file, " Split reuse change %d->%d:\n", + original_regno, new_regno); + dump_insn_slim (lra_dump_file, as_a <rtx_insn *> (usage_insn)); + } } } lra_assert (NOTE_P (usage_insn) || NONDEBUG_INSN_P (usage_insn)); @@ -5649,6 +5658,35 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn, return true; } +/* Split a hard reg for reload pseudo REGNO having RCLASS and living + in the range [FROM, TO]. Return true if did a split. Otherwise, + return false. */ +bool +spill_hard_reg_in_range (int regno, enum reg_class rclass, rtx_insn *from, rtx_insn *to) +{ + int i, hard_regno; + int rclass_size; + rtx_insn *insn; + + lra_assert (from != NULL && to != NULL); + rclass_size = ira_class_hard_regs_num[rclass]; + for (i = 0; i < rclass_size; i++) + { + hard_regno = ira_class_hard_regs[rclass][i]; + if (! TEST_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs, hard_regno)) + continue; + for (insn = from; insn != NEXT_INSN (to); insn = NEXT_INSN (insn)) + if (bitmap_bit_p (&lra_reg_info[hard_regno].insn_bitmap, + INSN_UID (insn))) + break; + if (insn != NEXT_INSN (to)) + continue; + if (split_reg (TRUE, hard_regno, from, NULL, to)) + return true; + } + return false; +} + /* Recognize that we need a split transformation for insn INSN, which defines or uses REGNO in its insn biggest MODE (we use it only if REGNO is a hard register). POTENTIAL_RELOAD_HARD_REGS contains @@ -5676,7 +5714,7 @@ split_if_necessary (int regno, machine_mode mode, || (GET_CODE (next_usage_insns) == INSN_LIST && (INSN_UID (XEXP (next_usage_insns, 0)) < max_uid))) && need_for_split_p (potential_reload_hard_regs, regno + i) - && split_reg (before_p, regno + i, insn, next_usage_insns)) + && split_reg (before_p, regno + i, insn, next_usage_insns, NULL)) res = true; return res; } @@ -6454,7 +6492,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail) head_p = false; } if (split_reg (false, j, bb_note (curr_bb), - next_usage_insns)) + next_usage_insns, NULL)) change_p = true; } usage_insns[j].check = 0; |