aboutsummaryrefslogtreecommitdiff
path: root/gcc/lra-constraints.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/lra-constraints.cc')
-rw-r--r--gcc/lra-constraints.cc150
1 files changed, 82 insertions, 68 deletions
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 0659aed..c941d2f 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -152,6 +152,9 @@ static machine_mode curr_operand_mode[MAX_RECOG_OPERANDS];
(e.g. constant) and whose subreg is given operand of the current
insn. VOIDmode in all other cases. */
static machine_mode original_subreg_reg_mode[MAX_RECOG_OPERANDS];
+/* The first call insn after curr_insn within the EBB during inherit_in_ebb
+ or NULL outside of that function. */
+static rtx_insn *first_call_insn;
@@ -1196,8 +1199,7 @@ match_reload (signed char out, signed char *ins, signed char *outs,
accurate. */
narrow_reload_pseudo_class (in_rtx, goal_class);
lra_emit_move (copy_rtx (new_in_reg), in_rtx);
- *before = get_insns ();
- end_sequence ();
+ *before = end_sequence ();
/* Add the new pseudo to consider values of subsequent input reload
pseudos. */
lra_assert (curr_insn_input_reloads_num < LRA_MAX_INSN_RELOADS);
@@ -1232,8 +1234,7 @@ match_reload (signed char out, signed char *ins, signed char *outs,
out_rtx = gen_rtx_STRICT_LOW_PART (VOIDmode, out_rtx);
lra_emit_move (out_rtx, copy_rtx (new_out_reg));
emit_insn (*after);
- *after = get_insns ();
- end_sequence ();
+ *after = end_sequence ();
}
*curr_id->operand_loc[out] = new_out_reg;
lra_update_dup (curr_id, out);
@@ -1441,8 +1442,7 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
emit_insn (GEN_FCN (sri.icode) (new_reg != NULL_RTX ? new_reg : dest,
src, scratch_reg));
}
- before = get_insns ();
- end_sequence ();
+ before = end_sequence ();
lra_process_new_insns (curr_insn, before, NULL, "Inserting the move");
if (new_reg != NULL_RTX)
SET_SRC (curr_insn_set) = new_reg;
@@ -1609,8 +1609,7 @@ process_addr_reg (rtx *loc, bool check_only_p, rtx_insn **before, rtx_insn **aft
{
push_to_sequence (*before);
lra_emit_move (new_reg, reg);
- *before = get_insns ();
- end_sequence ();
+ *before = end_sequence ();
}
*loc = new_reg;
if (after != NULL)
@@ -1618,8 +1617,7 @@ process_addr_reg (rtx *loc, bool check_only_p, rtx_insn **before, rtx_insn **aft
start_sequence ();
lra_emit_move (before_p ? copy_rtx (reg) : reg, new_reg);
emit_insn (*after);
- *after = get_insns ();
- end_sequence ();
+ *after = end_sequence ();
}
return true;
}
@@ -1636,16 +1634,14 @@ insert_move_for_subreg (rtx_insn **before, rtx_insn **after, rtx origreg,
{
push_to_sequence (*before);
lra_emit_move (newreg, origreg);
- *before = get_insns ();
- end_sequence ();
+ *before = end_sequence ();
}
if (after)
{
start_sequence ();
lra_emit_move (origreg, newreg);
emit_insn (*after);
- *after = get_insns ();
- end_sequence ();
+ *after = end_sequence ();
}
}
@@ -2420,14 +2416,15 @@ process_alt_operands (int only_alternative)
if (curr_static_id->operand[nop].type == OP_INOUT
|| curr_static_id->operand[m].type == OP_INOUT)
break;
- /* Operands don't match. If the operands are
- different user defined explicit hard
+ /* Operands don't match. For asm if the operands
+ are different user defined explicit hard
registers, then we cannot make them match
when one is early clobber operand. */
if ((REG_P (*curr_id->operand_loc[nop])
|| SUBREG_P (*curr_id->operand_loc[nop]))
&& (REG_P (*curr_id->operand_loc[m])
- || SUBREG_P (*curr_id->operand_loc[m])))
+ || SUBREG_P (*curr_id->operand_loc[m]))
+ && INSN_CODE (curr_insn) < 0)
{
rtx nop_reg = *curr_id->operand_loc[nop];
if (SUBREG_P (nop_reg))
@@ -3332,19 +3329,15 @@ process_alt_operands (int only_alternative)
first_conflict_j = j;
last_conflict_j = j;
/* Both the earlyclobber operand and conflicting operand
- cannot both be user defined hard registers. */
+ cannot both be user defined hard registers for asm.
+ Let curr_insn_transform diagnose it. */
if (HARD_REGISTER_P (operand_reg[i])
&& REG_USERVAR_P (operand_reg[i])
&& operand_reg[j] != NULL_RTX
&& HARD_REGISTER_P (operand_reg[j])
- && REG_USERVAR_P (operand_reg[j]))
- {
- /* For asm, let curr_insn_transform diagnose it. */
- if (INSN_CODE (curr_insn) < 0)
+ && REG_USERVAR_P (operand_reg[j])
+ && INSN_CODE (curr_insn) < 0)
return false;
- fatal_insn ("unable to generate reloads for "
- "impossible constraints:", curr_insn);
- }
}
if (last_conflict_j < 0)
continue;
@@ -3934,6 +3927,16 @@ process_address_1 (int nop, bool check_only_p,
enum reg_class cl;
rtx set;
rtx_insn *insns, *last_insn;
+
+ cl = base_reg_class (ad.mode, ad.as, ad.base_outer_code,
+ get_index_code (&ad), curr_insn);
+
+ if (REG_P (*ad.base_term)
+ && ira_class_subset_p[get_reg_class (REGNO (*ad.base_term))][cl])
+ /* It seems base reg is already in the base reg class and changing it
+ does not make a progress. So reload the whole inner address. */
+ goto reload_inner_addr;
+
/* Try to reload base into register only if the base is invalid
for the address but with valid offset, case (4) above. */
start_sequence ();
@@ -3979,8 +3982,6 @@ process_address_1 (int nop, bool check_only_p,
{
*ad.base_term = XEXP (SET_SRC (set), 0);
*ad.disp_term = XEXP (SET_SRC (set), 1);
- cl = base_reg_class (ad.mode, ad.as, ad.base_outer_code,
- get_index_code (&ad), curr_insn);
regno = REGNO (*ad.base_term);
if (regno >= FIRST_PSEUDO_REGISTER
&& cl != lra_get_allocno_class (regno))
@@ -4023,18 +4024,17 @@ process_address_1 (int nop, bool check_only_p,
}
else
{
- enum reg_class cl = base_reg_class (ad.mode, ad.as,
- SCRATCH, SCRATCH,
- curr_insn);
- rtx addr = *ad.inner;
-
+ enum reg_class cl;
+ rtx addr;
+ reload_inner_addr:
+ cl = base_reg_class (ad.mode, ad.as, SCRATCH, SCRATCH, curr_insn);
+ addr = *ad.inner;
new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr");
/* addr => new_base. */
lra_emit_move (new_reg, addr);
*ad.inner = new_reg;
}
- *before = get_insns ();
- end_sequence ();
+ *before = end_sequence ();
return true;
}
@@ -4049,14 +4049,21 @@ process_address (int nop, bool check_only_p,
rtx_insn **before, rtx_insn **after)
{
bool res = false;
-
- while (process_address_1 (nop, check_only_p, before, after))
+ /* Use enough iterations to process all address parts: */
+ for (int i = 0; i < 10; i++)
{
- if (check_only_p)
- return true;
- res = true;
+ if (!process_address_1 (nop, check_only_p, before, after))
+ {
+ return res;
+ }
+ else
+ {
+ if (check_only_p)
+ return true;
+ res = true;
+ }
}
- return res;
+ fatal_insn ("unable to reload address in ", curr_insn);
}
/* Override the generic address_reload_context in order to
@@ -4443,8 +4450,7 @@ curr_insn_transform (bool check_only_p)
push_to_sequence (before);
before = emit_spill_move (true, new_reg, src);
emit_insn (before);
- before = get_insns ();
- end_sequence ();
+ before = end_sequence ();
lra_process_new_insns (curr_insn, before, NULL, "Changing on");
lra_set_insn_deleted (curr_insn);
}
@@ -4464,8 +4470,7 @@ curr_insn_transform (bool check_only_p)
push_to_sequence (before);
before = emit_spill_move (true, new_reg, src);
emit_insn (before);
- before = get_insns ();
- end_sequence ();
+ before = end_sequence ();
lra_process_new_insns (curr_insn, before, NULL,
"Inserting the sec. move");
}
@@ -4736,8 +4741,7 @@ curr_insn_transform (bool check_only_p)
if (align_p)
emit_move_insn (new_reg, gen_rtx_AND (GET_MODE (new_reg), new_reg, XEXP (*loc, 1)));
}
- before = get_insns ();
- end_sequence ();
+ before = end_sequence ();
*loc = new_reg;
lra_update_dup (curr_id, i);
}
@@ -4810,8 +4814,7 @@ curr_insn_transform (bool check_only_p)
{
push_to_sequence (before);
lra_emit_move (new_reg, old);
- before = get_insns ();
- end_sequence ();
+ before = end_sequence ();
}
*loc = new_reg;
if (type != OP_IN
@@ -4822,8 +4825,7 @@ curr_insn_transform (bool check_only_p)
start_sequence ();
lra_emit_move (type == OP_INOUT ? copy_rtx (old) : old, new_reg);
emit_insn (after);
- after = get_insns ();
- end_sequence ();
+ after = end_sequence ();
*loc = new_reg;
}
for (j = 0; j < goal_alt_dont_inherit_ops_num; j++)
@@ -5965,8 +5967,7 @@ inherit_reload_reg (bool def_p, int original_regno,
lra_emit_move (original_reg, new_reg);
else
lra_emit_move (new_reg, original_reg);
- new_insns = get_insns ();
- end_sequence ();
+ new_insns = end_sequence ();
if (NEXT_INSN (new_insns) != NULL_RTX)
{
if (lra_dump_file != NULL)
@@ -6373,12 +6374,26 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
lra_process_new_insns (as_a <rtx_insn *> (usage_insn),
after_p ? NULL : restore,
after_p ? restore : NULL,
- call_save_p
- ? "Add reg<-save" : "Add reg<-split");
- lra_process_new_insns (insn, before_p ? save : NULL,
- before_p ? NULL : save,
- call_save_p
- ? "Add save<-reg" : "Add split<-reg");
+ call_save_p ? "Add reg<-save" : "Add reg<-split");
+ if (call_save_p
+ && first_call_insn != NULL
+ && BLOCK_FOR_INSN (first_call_insn) != BLOCK_FOR_INSN (insn))
+ /* PR116028: If original_regno is a pseudo that has been assigned a
+ callee-saved hard register, then emit the spill insn before the call
+ insn 'first_call_insn' instead of adjacent to 'insn'. If 'insn'
+ and 'first_call_insn' belong to the same EBB but to two separate
+ BBs, and if 'insn' is present in the entry BB, then generating the
+ spill insn in the entry BB can prevent shrink wrap from happening.
+ This is because the spill insn references the stack pointer and
+ hence the prolog gets generated in the entry BB itself. It is
+ also more efficient to generate the spill before
+ 'first_call_insn' as the spill now occurs only in the path
+ containing the call. */
+ lra_process_new_insns (first_call_insn, save, NULL, "Add save<-reg");
+ else
+ lra_process_new_insns (insn, before_p ? save : NULL,
+ before_p ? NULL : save,
+ call_save_p ? "Add save<-reg" : "Add split<-reg");
if (nregs > 1 || original_regno < FIRST_PSEUDO_REGISTER)
/* If we are trying to split multi-register. We should check
conflicts on the next assignment sub-pass. IRA can allocate on
@@ -6484,7 +6499,7 @@ split_if_necessary (int regno, machine_mode mode,
&& (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, NULL))
- res = true;
+ res = true;
return res;
}
@@ -6591,14 +6606,12 @@ process_invariant_for_inheritance (rtx dst_reg, rtx invariant_rtx)
lra_reg_info[REGNO (new_reg)].restore_rtx = PATTERN (insn);
start_sequence ();
lra_emit_move (new_reg, dst_reg);
- new_insns = get_insns ();
- end_sequence ();
+ new_insns = end_sequence ();
lra_process_new_insns (curr_insn, NULL, new_insns,
"Add invariant inheritance<-original");
start_sequence ();
lra_emit_move (SET_DEST (insn_set), new_reg);
- new_insns = get_insns ();
- end_sequence ();
+ new_insns = end_sequence ();
lra_process_new_insns (insn, NULL, new_insns,
"Changing reload<-inheritance");
lra_set_insn_deleted (insn);
@@ -7074,6 +7087,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
last_call_for_abi[callee_abi.id ()] = calls_num;
full_and_partial_call_clobbers
|= callee_abi.full_and_partial_reg_clobbers ();
+ first_call_insn = curr_insn;
if ((cheap = find_reg_note (curr_insn,
REG_RETURNED, NULL_RTX)) != NULL_RTX
&& ((cheap = XEXP (cheap, 0)), true)
@@ -7099,8 +7113,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
{
start_sequence ();
emit_move_insn (cheap, copy_rtx (dest));
- restore = get_insns ();
- end_sequence ();
+ restore = end_sequence ();
lra_process_new_insns (curr_insn, NULL, restore,
"Inserting call parameter restore");
/* We don't need to save/restore of the pseudo from
@@ -7142,6 +7155,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
{
bool before_p;
rtx_insn *use_insn = curr_insn;
+ rtx_insn *prev_insn = PREV_INSN (curr_insn);
before_p = (JUMP_P (curr_insn)
|| (CALL_P (curr_insn) && reg->type == OP_IN));
@@ -7156,7 +7170,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
change_p = true;
/* Invalidate. */
usage_insns[src_regno].check = 0;
- if (before_p)
+ if (before_p && PREV_INSN (curr_insn) != prev_insn)
use_insn = PREV_INSN (curr_insn);
}
if (NONDEBUG_INSN_P (curr_insn))
@@ -7278,6 +7292,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
}
}
}
+ first_call_insn = NULL;
return change_p;
}
@@ -7478,8 +7493,7 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
/* We cannot just change the source. It might be
an insn different from the move. */
emit_insn (lra_reg_info[sregno].restore_rtx);
- rtx_insn *new_insns = get_insns ();
- end_sequence ();
+ rtx_insn *new_insns = end_sequence ();
lra_assert (single_set (new_insns) != NULL
&& SET_DEST (set) == SET_DEST (single_set (new_insns)));
lra_process_new_insns (curr_insn, NULL, new_insns,