The invalid RTL was introduced by the following peephole in i386.md:
;; After splitting up read-modify operations, array accesses with memory ;; operands might end up in form: ;; sall $2, %eax ;; movl 4(%esp), %edx ;; addl %edx, %eax ;; instead of pre-splitting: ;; sall $2, %eax ;; addl 4(%esp), %eax ;; Turn it into: ;; movl 4(%esp), %edx ;; leal (%edx,%eax,4), %eax
(define_peephole2 [(match_scratch:SI 5 "r") (parallel [(set (match_operand 0 "register_operand" "") (ashift (match_operand 1 "register_operand" "") (match_operand 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_operand 3 "register_operand" "") (plus (match_dup 0) (match_operand 4 "x86_64_general_operand" ""))) (clobber (reg:CC FLAGS_REG))])] "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3 /* Validate MODE for lea. */ && ((!TARGET_PARTIAL_REG_STALL && (GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)) || GET_MODE (operands[0]) == SImode || (TARGET_64BIT && GET_MODE (operands[0]) == DImode)) /* We reorder load and the shift. */ && !reg_overlap_mentioned_p (operands[0], operands[4])" [(set (match_dup 5) (match_dup 4)) (set (match_dup 0) (match_dup 1))] { enum machine_mode mode = GET_MODE (operands[1]) == DImode ? DImode : SImode; int scale = 1 << INTVAL (operands[2]); rtx index = gen_lowpart (Pmode, operands[1]); rtx base = gen_lowpart (Pmode, operands[5]); rtx dest = gen_lowpart (mode, operands[3]);
operands[1] = gen_rtx_PLUS (Pmode, base, gen_rtx_MULT (Pmode, index, GEN_INT (scale))); if (mode != Pmode) operands[1] = gen_rtx_SUBREG (mode, operands[1], 0); operands[5] = base; operands[0] = dest; })
Note how operands[5] is always DImode, while operands[4] may be some other mode.
The invalid RTL was introduced by the following peephole in i386.md:
;; After splitting up read-modify operations, array accesses with memory
;; operands might end up in form:
;; sall $2, %eax
;; movl 4(%esp), %edx
;; addl %edx, %eax
;; instead of pre-splitting:
;; sall $2, %eax
;; addl 4(%esp), %eax
;; Turn it into:
;; movl 4(%esp), %edx
;; leal (%edx,%eax,4), %eax
(define_peephole2 scratch: SI 5 "r")
(ashift (match_operand 1 "register_operand" "")
( match_operand 2 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))])
(plus (match_dup 0)
(match_ operand 4 "x86_64_ general_ operand" "")))
(clobber (reg:CC FLAGS_REG))])] PARTIAL_ REG_STALL mentioned_ p (operands[0], operands[4])"
[(match_
(parallel [(set (match_operand 0 "register_operand" "")
(parallel [(set (match_operand 3 "register_operand" "")
"INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
/* Validate MODE for lea. */
&& ((!TARGET_
&& (GET_MODE (operands[0]) == QImode
|| GET_MODE (operands[0]) == HImode))
|| GET_MODE (operands[0]) == SImode
|| (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
/* We reorder load and the shift. */
&& !reg_overlap_
[(set (match_dup 5) (match_dup 4))
(set (match_dup 0) (match_dup 1))]
{
enum machine_mode mode = GET_MODE (operands[1]) == DImode ? DImode : SImode;
int scale = 1 << INTVAL (operands[2]);
rtx index = gen_lowpart (Pmode, operands[1]);
rtx base = gen_lowpart (Pmode, operands[5]);
rtx dest = gen_lowpart (mode, operands[3]);
operands[1] = gen_rtx_PLUS (Pmode, base,
gen_rtx_ MULT (Pmode, index, GEN_INT (scale)));
if (mode != Pmode)
operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
operands[5] = base;
operands[0] = dest;
})
Note how operands[5] is always DImode, while operands[4] may be some other mode.