diff options
author | Wilco Dijkstra <wdijkstr@arm.com> | 2017-05-24 17:06:55 +0000 |
---|---|---|
committer | Wilco Dijkstra <wilco@gcc.gnu.org> | 2017-05-24 17:06:55 +0000 |
commit | 1a2fa2f821eec4395ff8869232d0e4e49afbe64b (patch) | |
tree | 3947dcce7024d126e21371e663b2a9aa5f9c6d78 /gcc | |
parent | c0edbb32c15b1c5c2145294641e1dec688d23adc (diff) | |
download | gcc-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/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/lra-remat.c | 22 |
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) |