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
This commit is contained in:
parent
c0edbb32c1
commit
1a2fa2f821
@ -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>
|
2017-05-24 Sheldon Lobo <smlobo@sheldon.us.oracle.com>
|
||||||
|
|
||||||
* config/sparc/sparc.md (length): Return the correct value for -mflat
|
* config/sparc/sparc.md (length): Return the correct value for -mflat
|
||||||
|
@ -1117,6 +1117,7 @@ do_remat (void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int i, hard_regno, nregs;
|
int i, hard_regno, nregs;
|
||||||
|
int dst_hard_regno, dst_nregs;
|
||||||
rtx_insn *remat_insn = NULL;
|
rtx_insn *remat_insn = NULL;
|
||||||
HOST_WIDE_INT cand_sp_offset = 0;
|
HOST_WIDE_INT cand_sp_offset = 0;
|
||||||
if (cand != NULL)
|
if (cand != NULL)
|
||||||
@ -1131,6 +1132,12 @@ do_remat (void)
|
|||||||
gcc_assert (REG_P (saved_op));
|
gcc_assert (REG_P (saved_op));
|
||||||
int ignore_regno = REGNO (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)
|
for (reg = cand_id->regs; reg != NULL; reg = reg->next)
|
||||||
if (reg->type != OP_IN && reg->regno != ignore_regno)
|
if (reg->type != OP_IN && reg->regno != ignore_regno)
|
||||||
{
|
{
|
||||||
@ -1141,6 +1148,10 @@ do_remat (void)
|
|||||||
break;
|
break;
|
||||||
if (i < nregs)
|
if (i < nregs)
|
||||||
break;
|
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)
|
if (reg == NULL)
|
||||||
@ -1148,9 +1159,14 @@ do_remat (void)
|
|||||||
for (reg = static_cand_id->hard_regs;
|
for (reg = static_cand_id->hard_regs;
|
||||||
reg != NULL;
|
reg != NULL;
|
||||||
reg = reg->next)
|
reg = reg->next)
|
||||||
if (reg->type != OP_IN
|
if (reg->type != OP_IN)
|
||||||
&& TEST_HARD_REG_BIT (live_hard_regs, reg->regno))
|
{
|
||||||
break;
|
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)
|
if (reg == NULL)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user