aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorWilco Dijkstra <wdijkstr@arm.com>2017-05-24 17:06:55 +0000
committerWilco Dijkstra <wilco@gcc.gnu.org>2017-05-24 17:06:55 +0000
commit1a2fa2f821eec4395ff8869232d0e4e49afbe64b (patch)
tree3947dcce7024d126e21371e663b2a9aa5f9c6d78 /gcc
parentc0edbb32c15b1c5c2145294641e1dec688d23adc (diff)
downloadgcc-1a2fa2f821eec4395ff8869232d0e4e49afbe64b.zip
gcc-1a2fa2f821eec4395ff8869232d0e4e49afbe64b.tar.gz
gcc-1a2fa2f821eec4395ff8869232d0e4e49afbe64b.tar.bz2
When lra-remat rematerializes an instruction with a clobber, it checks that the clobber does not kill live registers.
When lra-remat rematerializes an instruction with a clobber, it checks that the clobber does not kill live registers. However it fails to check that the clobber also doesn't overlap with the destination register of the final rematerialized instruction. As a result it is possible to generate illegal instructions with the same hard register as the destination and a clobber. Fix this by also checking for overlaps with the destination register. gcc/ PR rtl-optimization/80754 * lra-remat.c (do_remat): Add overlap checks for dst_regno. From-SVN: r248424
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/lra-remat.c22
2 files changed, 24 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 69356fc..1b70fa0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2017-05-24 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR rtl-optimization/80754
+ * lra-remat.c (do_remat): Add overlap checks for dst_regno.
+
2017-05-24 Sheldon Lobo <smlobo@sheldon.us.oracle.com>
* config/sparc/sparc.md (length): Return the correct value for -mflat
diff --git a/gcc/lra-remat.c b/gcc/lra-remat.c
index fb294ed..f28993e 100644
--- a/gcc/lra-remat.c
+++ b/gcc/lra-remat.c
@@ -1117,6 +1117,7 @@ do_remat (void)
break;
}
int i, hard_regno, nregs;
+ int dst_hard_regno, dst_nregs;
rtx_insn *remat_insn = NULL;
HOST_WIDE_INT cand_sp_offset = 0;
if (cand != NULL)
@@ -1131,6 +1132,12 @@ do_remat (void)
gcc_assert (REG_P (saved_op));
int ignore_regno = REGNO (saved_op);
+ dst_hard_regno = dst_regno < FIRST_PSEUDO_REGISTER
+ ? dst_regno : reg_renumber[dst_regno];
+ gcc_assert (dst_hard_regno >= 0);
+ machine_mode mode = GET_MODE (SET_DEST (set));
+ dst_nregs = hard_regno_nregs[dst_hard_regno][mode];
+
for (reg = cand_id->regs; reg != NULL; reg = reg->next)
if (reg->type != OP_IN && reg->regno != ignore_regno)
{
@@ -1141,6 +1148,10 @@ do_remat (void)
break;
if (i < nregs)
break;
+ /* Ensure the clobber also doesn't overlap dst_regno. */
+ if (hard_regno + nregs > dst_hard_regno
+ && hard_regno < dst_hard_regno + dst_nregs)
+ break;
}
if (reg == NULL)
@@ -1148,9 +1159,14 @@ do_remat (void)
for (reg = static_cand_id->hard_regs;
reg != NULL;
reg = reg->next)
- if (reg->type != OP_IN
- && TEST_HARD_REG_BIT (live_hard_regs, reg->regno))
- break;
+ if (reg->type != OP_IN)
+ {
+ if (TEST_HARD_REG_BIT (live_hard_regs, reg->regno))
+ break;
+ if (reg->regno >= dst_hard_regno
+ && reg->regno < dst_hard_regno + dst_nregs)
+ break;
+ }
}
if (reg == NULL)