[Bug rtl-optimization/68623] New: lra doesn't check predicate after reloading an early clobber
mrs at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Mon Nov 30 17:50:00 GMT 2015
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68623
Bug ID: 68623
Summary: lra doesn't check predicate after reloading an early
clobber
Product: gcc
Version: 6.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: mrs at gcc dot gnu.org
Target Milestone: ---
lra doesn't check the predicate after reload an output register to ensure the
instruction remains valid. The predicate is the load_multiple_operation and it
ensures that the hard registers are sequential. When the first output register
is the same as the address, then the input register must be reloaded. The
output register cannot be, unless all the output registers are and then the
specific property embodied by load_multiple_operation would need to be
preserved. Here is the pattern:
(define_insn "*ldmdi2"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:DI 1 "a_hard_register_operand" "=&r")
(mem:DI (match_operand:DI 2 "register_operand" "r")))
(set (match_operand:DI 3 "c1_hard_register_operand" "")
(mem:DI (plus:DI (match_dup 2) (match_operand 4 "const_int_operand"
"KS10"))))])]
""
"ldm\t%1,{%2,%3|0(%2),2}"
[(set_attr "type" "ldm")
(set_attr "count" "2")])
and the instruction after reload:
(insn 28 27 55 2 (parallel [
(set (reg:DI 27 $work1 [208])
(mem:DI (reg/v/f:DI 19 $a1 [orig:187 p ] [187]) [0 S8 A64]))
(set (reg:DI 20 $a2)
(mem:DI (plus:DI (reg/v/f:DI 19 $a1 [orig:187 p ] [187])
(const_int 8 [0x8])) [0 S8 A64]))
]) t.c:28 349 {*ldmdi2}
(nil))
before reload, $a1 is set in the first set. $a1 and $a2 are sequential. The
predicate:
(define_predicate "load_multiple_operation"
(match_code "parallel")
{
int count = XVECLEN (op, 0);
int dest_regno;
rtx src_addr;
int i;
/* Perform a quick check so we don't blow up below. */
if (count <= 1
|| GET_CODE (XVECEXP (op, 0, 0)) != SET
|| GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
|| GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
return 0;
dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
if (dest_regno >= FIRST_PSEUDO_REGISTER
|| (dest_regno + count) > FIRST_PSEUDO_REGISTER)
return 0;
/* Check, is base, or base + displacement. */
if (GET_CODE (src_addr) != REG)
return 0;
for (i = 1; i < count; i++)
{
rtx elt = XVECEXP (op, 0, i);
if (debugit) {
printf("i = %d\n",i);
debug_rtx(elt);
}
if (GET_CODE (elt) != SET
|| GET_CODE (SET_DEST (elt)) != REG
|| GET_MODE (SET_DEST (elt)) != DImode
|| REGNO (SET_DEST (elt)) != (unsigned) (dest_regno + i)
|| GET_CODE (SET_SRC (elt)) != MEM
|| GET_MODE (SET_SRC (elt)) != DImode
|| GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
|| ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
|| GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
|| INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 8)
return 0;
}
return 1;
})
More information about the Gcc-bugs
mailing list