From: Peter Bergner <bergner@linux.ibm.com>
To: GCC Patches <gcc-patches@gcc.gnu.org>
Cc: Vladimir N Makarov <vmakarov@redhat.com>, Jeff Law <law@redhat.com>
Subject: [PATCH 2/2][IRA,LRA] Fix PR86939, IRA incorrectly creates an interference between a pseudo register and a hard register
Date: Wed, 26 Sep 2018 21:36:00 -0000 [thread overview]
Message-ID: <9b46a22e-607d-981d-7686-7d25cace39e9@linux.ibm.com> (raw)
In-Reply-To: <db00fba8-f392-510f-7f75-31dd1eed6f87@linux.ibm.com>
gcc/
* ira.h (copy_insn_p): New prototype.
* ira-lives.c (ignore_reg_for_conflicts): New static variable.
(make_hard_regno_dead): Don't add conflicts for register
ignore_reg_for_conflicts.
(make_object_dead): Likewise.
(copy_insn_p): New function.
(process_bb_node_lives): Set ignore_reg_for_conflicts for copies.
* lra-lives.c (ignore_reg_for_conflicts): New static variable.
(make_hard_regno_dead): Don't add conflicts for register
ignore_reg_for_conflicts.
(mark_pseudo_dead): Likewise.
(process_bb_lives): Set ignore_reg_for_conflicts for copies.
gcc/testsuite/
* gcc.target/powerpc/pr86939.c: New test.
Index: gcc/ira.h
===================================================================
--- gcc/ira.h (revision 263506)
+++ gcc/ira.h (working copy)
@@ -210,6 +210,9 @@ extern void ira_adjust_equiv_reg_cost (u
/* ira-costs.c */
extern void ira_costs_c_finalize (void);
+/* ira-lives.c */
+extern rtx copy_insn_p (rtx_insn *);
+
/* Spilling static chain pseudo may result in generation of wrong
non-local goto code using frame-pointer to address saved stack
pointer value after restoring old frame pointer value. The
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c (revision 263506)
+++ gcc/ira-lives.c (working copy)
@@ -84,6 +84,10 @@ static int *allocno_saved_at_call;
supplemental to recog_data. */
static alternative_mask preferred_alternatives;
+/* If non-NULL, the source operand of a register to register copy for which
+ we should not add a conflict with the copy's destination operand. */
+static rtx ignore_reg_for_conflicts;
+
/* Record hard register REGNO as now being live. */
static void
make_hard_regno_live (int regno)
@@ -101,6 +105,11 @@ make_hard_regno_dead (int regno)
{
ira_object_t obj = ira_object_id_map[i];
+ if (ignore_reg_for_conflicts != NULL_RTX
+ && REGNO (ignore_reg_for_conflicts)
+ == (unsigned int) ALLOCNO_REGNO (OBJECT_ALLOCNO (obj)))
+ continue;
+
SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), regno);
SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), regno);
}
@@ -154,12 +163,38 @@ static void
make_object_dead (ira_object_t obj)
{
live_range_t lr;
+ int ignore_regno = -1;
+ int last_regno = -1;
sparseset_clear_bit (objects_live, OBJECT_CONFLICT_ID (obj));
+ /* Check whether any part of IGNORE_REG_FOR_CONFLICTS already conflicts
+ with OBJ. */
+ if (ignore_reg_for_conflicts != NULL_RTX
+ && REGNO (ignore_reg_for_conflicts) < FIRST_PSEUDO_REGISTER)
+ {
+ last_regno = END_REGNO (ignore_reg_for_conflicts);
+ int src_regno = ignore_regno = REGNO (ignore_reg_for_conflicts);
+
+ while (src_regno < last_regno)
+ {
+ if (TEST_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), src_regno))
+ {
+ ignore_regno = last_regno = -1;
+ break;
+ }
+ src_regno++;
+ }
+ }
+
IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), hard_regs_live);
IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), hard_regs_live);
+ /* If IGNORE_REG_FOR_CONFLICTS did not already conflict with OBJ, make
+ sure it still doesn't. */
+ for (; ignore_regno < last_regno; ignore_regno++)
+ CLEAR_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), ignore_regno);
+
lr = OBJECT_LIVE_RANGES (obj);
ira_assert (lr != NULL);
lr->finish = curr_point;
@@ -1022,6 +1057,38 @@ find_call_crossed_cheap_reg (rtx_insn *i
return cheap_reg;
}
+/* Determine whether INSN is a register to register copy of the type where
+ we do not need to make the source and destiniation registers conflict.
+ If this is a copy instruction, then return the source reg. Otherwise,
+ return NULL_RTX. */
+rtx
+copy_insn_p (rtx_insn *insn)
+{
+ rtx set;
+
+ /* Disallow anything other than a simple register to register copy
+ that has no side effects. */
+ if ((set = single_set (insn)) == NULL_RTX
+ || !REG_P (SET_DEST (set))
+ || !REG_P (SET_SRC (set))
+ || side_effects_p (set))
+ return NULL_RTX;
+
+ int dst_regno = REGNO (SET_DEST (set));
+ int src_regno = REGNO (SET_SRC (set));
+ machine_mode mode = GET_MODE (SET_DEST (set));
+
+ /* Computing conflicts for register pairs is difficult to get right, so
+ for now, disallow it. */
+ if ((dst_regno < FIRST_PSEUDO_REGISTER
+ && hard_regno_nregs (dst_regno, mode) != 1)
+ || (src_regno < FIRST_PSEUDO_REGISTER
+ && hard_regno_nregs (src_regno, mode) != 1))
+ return NULL_RTX;
+
+ return SET_SRC (set);
+}
+
/* Process insns of the basic block given by its LOOP_TREE_NODE to
update allocno live ranges, allocno hard register conflicts,
intersected calls, and register pressure info for allocnos for the
@@ -1107,6 +1174,7 @@ process_bb_node_lives (ira_loop_tree_nod
curr_point);
call_p = CALL_P (insn);
+ ignore_reg_for_conflicts = copy_insn_p (insn);
#ifdef REAL_PIC_OFFSET_TABLE_REGNUM
int regno;
bool clear_pic_use_conflict_p = false;
@@ -1289,6 +1357,7 @@ process_bb_node_lives (ira_loop_tree_nod
#endif
curr_point++;
}
+ ignore_reg_for_conflicts = NULL_RTX;
if (bb_has_eh_pred (bb))
for (j = 0; ; ++j)
Index: gcc/ira-lives.c
===================================================================
--- gcc/lra-lives.c (revision 263506)
+++ gcc/lra-lives.c (working copy)
@@ -96,6 +96,10 @@ static bitmap_head temp_bitmap;
/* Pool for pseudo live ranges. */
static object_allocator<lra_live_range> lra_live_range_pool ("live ranges");
+/* If non-NULL, the source operand of a register to register copy for which
+ we should not add a conflict with the copy's destination operand. */
+static rtx ignore_reg_for_conflicts;
+
/* Free live range list LR. */
static void
free_live_range_list (lra_live_range_t lr)
@@ -251,13 +255,18 @@ make_hard_regno_dead (int regno, bool ch
sparseset_set_bit (start_dying, regno);
unsigned int i;
EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
+ {
+ if (ignore_reg_for_conflicts != NULL_RTX
+ && REGNO (ignore_reg_for_conflicts) == i)
+ continue;
#ifdef REAL_PIC_OFFSET_TABLE_REGNUM
- if (! check_pic_pseudo_p
- || regno != REAL_PIC_OFFSET_TABLE_REGNUM
- || pic_offset_table_rtx == NULL
- || i != REGNO (pic_offset_table_rtx))
+ if (! check_pic_pseudo_p
+ || regno != REAL_PIC_OFFSET_TABLE_REGNUM
+ || pic_offset_table_rtx == NULL
+ || i != REGNO (pic_offset_table_rtx))
#endif
- SET_HARD_REG_BIT (lra_reg_info[i].conflict_hard_regs, regno);
+ SET_HARD_REG_BIT (lra_reg_info[i].conflict_hard_regs, regno);
+ }
CLEAR_HARD_REG_BIT (hard_regs_live, regno);
if (fixed_regs[regno] || TEST_HARD_REG_BIT (hard_regs_spilled_into, regno))
{
@@ -294,14 +303,41 @@ static void
mark_pseudo_dead (int regno, int point)
{
lra_live_range_t p;
+ int ignore_regno = -1;
+ int last_regno = -1;
lra_assert (regno >= FIRST_PSEUDO_REGISTER);
lra_assert (sparseset_bit_p (pseudos_live, regno));
sparseset_clear_bit (pseudos_live, regno);
sparseset_set_bit (start_dying, regno);
+ /* Check whether any part of IGNORE_REG_FOR_CONFLICTS already conflicts
+ with REGNO. */
+ if (ignore_reg_for_conflicts != NULL_RTX
+ && REGNO (ignore_reg_for_conflicts) < FIRST_PSEUDO_REGISTER)
+ {
+ last_regno = END_REGNO (ignore_reg_for_conflicts);
+ int src_regno = ignore_regno = REGNO (ignore_reg_for_conflicts);
+
+ while (src_regno < last_regno)
+ {
+ if (TEST_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs,
+ src_regno))
+ {
+ ignore_regno = last_regno = -1;
+ break;
+ }
+ src_regno++;
+ }
+ }
+
IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs, hard_regs_live);
+ /* If IGNORE_REG_FOR_CONFLICTS did not already conflict with REGNO, make
+ sure it still doesn't. */
+ for (; ignore_regno < last_regno; ignore_regno++)
+ CLEAR_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs, ignore_regno);
+
if (complete_info_p || lra_get_regno_hard_regno (regno) < 0)
{
p = lra_reg_info[regno].live_ranges;
@@ -747,6 +783,7 @@ process_bb_lives (basic_block bb, int &c
}
call_p = CALL_P (curr_insn);
+ ignore_reg_for_conflicts = copy_insn_p (curr_insn);
src_regno = (set != NULL_RTX && REG_P (SET_SRC (set))
? REGNO (SET_SRC (set)) : -1);
dst_regno = (set != NULL_RTX && REG_P (SET_DEST (set))
@@ -989,6 +1026,7 @@ process_bb_lives (basic_block bb, int &c
EXECUTE_IF_SET_IN_SPARSESET (unused_set, j)
add_reg_note (curr_insn, REG_UNUSED, regno_reg_rtx[j]);
}
+ ignore_reg_for_conflicts = NULL_RTX;
if (bb_has_eh_pred (bb))
for (j = 0; ; ++j)
Index: gcc/testsuite/gcc.target/powerpc/pr86939.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr86939.c (nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/pr86939.c (working copy)
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2" } */
+
+typedef long (*fptr_t) (void);
+long
+func (fptr_t *p)
+{
+ if (p)
+ return (*p) ();
+ return 0;
+}
+/* { dg-final { scan-assembler-not {mr %?r?12,} } } */
next prev parent reply other threads:[~2018-09-26 21:16 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-26 21:14 [PATCH 0/2][IRA,LRA] " Peter Bergner
2018-09-26 21:16 ` [PATCH 1/2][IRA,LRA] " Peter Bergner
2018-09-26 21:36 ` Peter Bergner [this message]
2018-09-28 21:45 ` [PATCH 0/2][IRA,LRA] " Vladimir Makarov
2018-09-30 20:28 ` Peter Bergner
2018-10-01 0:57 ` H.J. Lu
2018-10-01 1:18 ` Peter Bergner
2018-10-01 12:46 ` H.J. Lu
2018-10-01 12:51 ` H.J. Lu
2018-10-01 13:16 ` H.J. Lu
2018-10-01 14:05 ` Peter Bergner
2018-10-02 4:08 ` Peter Bergner
2018-10-02 14:50 ` Jeff Law
2018-10-02 15:07 ` Peter Bergner
2018-10-02 15:37 ` H.J. Lu
2018-10-02 15:55 ` Peter Bergner
2018-10-02 17:14 ` H.J. Lu
2018-10-02 21:53 ` Peter Bergner
2018-10-02 22:28 ` H.J. Lu
2018-10-03 0:35 ` Peter Bergner
2018-10-03 2:23 ` H.J. Lu
2018-10-03 2:46 ` Peter Bergner
2018-10-03 14:43 ` [PATCH 2/2 v3][IRA,LRA] " Peter Bergner
2018-10-04 22:18 ` Vladimir Makarov
2018-10-05 16:50 ` Peter Bergner
2018-10-05 18:54 ` Vladimir Makarov
2018-10-05 20:10 ` Peter Bergner
2018-10-05 22:56 ` Vladimir Makarov
2018-10-06 6:40 ` Peter Bergner
2018-10-08 9:37 ` Christophe Lyon
2018-10-08 14:21 ` Peter Bergner
2018-10-08 14:46 ` Christophe Lyon
2018-10-08 15:04 ` Jeff Law
2018-10-11 2:57 ` Peter Bergner
2018-10-11 18:26 ` Peter Bergner
2018-10-11 20:31 ` Peter Bergner
2018-10-11 20:46 ` Jeff Law
2018-10-11 21:09 ` Peter Bergner
2018-10-11 21:36 ` Jeff Law
2018-10-12 9:50 ` Eric Botcazou
2018-10-11 21:05 ` Vladimir Makarov
2018-10-12 16:57 ` Peter Bergner
2018-10-12 17:56 ` Jeff Law
2018-10-12 4:44 ` Jeff Law
2018-10-16 2:50 ` Peter Bergner
2018-11-01 18:50 ` Renlin Li
2018-11-01 20:35 ` Segher Boessenkool
2018-11-01 22:08 ` Peter Bergner
2018-11-02 10:05 ` Renlin Li
2018-11-05 19:20 ` Jeff Law
2018-11-05 19:36 ` Peter Bergner
2018-11-05 19:41 ` Jeff Law
2018-11-06 10:52 ` Renlin Li
2018-11-06 10:57 ` Ramana Radhakrishnan
2018-11-06 12:23 ` Renlin Li
2018-11-06 18:46 ` Peter Bergner
2018-11-06 18:58 ` Jeff Law
2018-11-08 10:57 ` Renlin Li
2018-11-08 11:49 ` Richard Biener
2018-11-08 14:29 ` Peter Bergner
2018-11-08 19:01 ` Peter Bergner
2018-11-08 12:35 ` Peter Bergner
2018-11-08 13:42 ` Renlin Li
2018-11-08 15:21 ` Peter Bergner
2018-11-08 16:20 ` Renlin Li
2018-11-08 17:52 ` Peter Bergner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9b46a22e-607d-981d-7686-7d25cace39e9@linux.ibm.com \
--to=bergner@linux.ibm.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=law@redhat.com \
--cc=vmakarov@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).