From fb530c72edd80bfdb02dd3a2f17e8df61b097859 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 3 Nov 2005 00:21:22 +0100 Subject: [PATCH] re PR target/23303 (4.1 generates sall + addl instead of leal) PR target/23303 * i386.md: Add peep2 for simplyfing array accesses. * gcc.dg/i386-lea.c: New test From-SVN: r106406 --- gcc/ChangeLog | 5 +++ gcc/config/i386/i386.md | 58 +++++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/i386-lea.c | 14 ++++++++ 4 files changed, 82 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/i386-lea.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 59654738319..afca62bfa1a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2005-11-02 Jan Hubicka + + PR target/23303 + * i386.md: Add peep2 for simplyfing array accesses. + 2005-11-02 Ulrich Weigand PR target/24615 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 3e417b500da..19d874bce84 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -19785,6 +19785,64 @@ 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]) + && !reg_overlap_mentioned_p (operands[0], operands[4]) + /* 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))] +{ + enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode; + int scale = 1 << INTVAL (operands[2]); + rtx index = gen_lowpart (Pmode, operands[1]); + rtx base = gen_lowpart (Pmode, operands[3]); + rtx dest = gen_lowpart (mode, operands[5]); + + 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[0] = dest; +}) ;; Call-value patterns last so that the wildcard operand does not ;; disrupt insn-recog's switch tables. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5fee48f1bc1..058fcb30e3e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-11-02 Jan Hubicka + + PR target/23303 + * gcc.dg/i386-lea.c: New test + 2005-11-02 Ulrich Weigand PR target/24615 diff --git a/gcc/testsuite/gcc.dg/i386-lea.c b/gcc/testsuite/gcc.dg/i386-lea.c new file mode 100644 index 00000000000..61d9955f3e2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/i386-lea.c @@ -0,0 +1,14 @@ +/* { dg-do compile { 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]; +} -- 2.30.2