Comment 1 for bug 701733

Revision history for this message
Ulrich Weigand (uweigand) wrote : Re: x86_64 gcc build failure with 2011.01-0

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.