------- Comment #5 from hubicka at ucw dot cz 2005-10-31 20:25 ------- Subject: Re: [4.1 Regression] 4.1 generates sall + addl instead of leal
> > > ------- Comment #4 from mmitchel at gcc dot gnu dot org 2005-10-31 04:45 > ------- > Jan, what's your analysis on this PR? Hmm, I am still not sure if it matters too much, but since there are actually dupes of this problem, I think we can simply add peep2 fixing this particular common case. I am testing attached patch. /* { dg-do assemble { target i?86-*-* x86_64-*-* } } */ /* { dg-require-effective-target ilp32 } */ /* { dg-options "-O2 -march=i686" } */ /* { dg-final { scan-assembler "leal" } } */ typedef struct { char **visbuf; char **allbuf; } TScreen; void VTallocbuf(TScreen *screen, unsigned long savelines) { screen->visbuf = &screen->allbuf[savelines]; } 2005-10-31 Jan Hubicka <[EMAIL PROTECTED]> PR target/23303 * i386.md: Add peep2 for simplyfing array accesses. Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 106275) +++ config/i386/i386.md (working copy) @@ -19785,6 +19785,58 @@ if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); }) + +;; 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 + [(parallel [(set (match_operand 0 "register_operand" "") + (ashift (match_operand 1 "register_operand" "") + (match_operand 2 "const_int_operand" ""))) + (clobber (reg:CC FLAGS_REG))]) + (set (match_operand 3 "register_operand") + (match_operand 4 "x86_64_general_operand" "")) + (parallel [(set (match_operand 5 "register_operand" "") + (plus (match_operand 6 "register_operand" "") + (match_operand 7 "register_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. */ + && !rtx_equal_p (operands[1], operands[3]) + /* Last PLUS must consist of operand 0 and 3. */ + && !rtx_equal_p (operands[0], operands[3]) + && (rtx_equal_p (operands[3], operands[6]) + || rtx_equal_p (operands[3], operands[7])) + && (rtx_equal_p (operands[0], operands[6]) + || rtx_equal_p (operands[0], operands[7])) + /* The intermediate operand 0 must die or be same as output. */ + && (rtx_equal_p (operands[0], operands[5]) + || peep2_reg_dead_p (3, operands[0]))" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (match_dup 1))] +{ + int scale = 1 << INTVAL (operands[2]); + rtx index = gen_lowpart (Pmode, operands[1]); + rtx base = gen_lowpart (Pmode, operands[3]); + rtx dest = gen_lowpart (Pmode, operands[5]); + + operands[1] = gen_rtx_PLUS (Pmode, base, gen_rtx_MULT (Pmode, index, GEN_INT (scale))); + operands[0] = dest; +}) ;; Call-value patterns last so that the wildcard operand does not ;; disrupt insn-recog's switch tables. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23303