OSDN Git Service

PR target/23303
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Nov 2005 23:21:22 +0000 (23:21 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Nov 2005 23:21:22 +0000 (23:21 +0000)
* i386.md: Add peep2 for simplyfing array accesses.
* gcc.dg/i386-lea.c: New test

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@106406 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/i386-lea.c [new file with mode: 0644]

index 5965473..afca62b 100644 (file)
@@ -1,3 +1,8 @@
+2005-11-02  Jan Hubicka  <jh@suse.cz>
+
+       PR target/23303
+       * i386.md: Add peep2 for simplyfing array accesses.
+
 2005-11-02  Ulrich Weigand  <uweigand@de.ibm.com>
 
        PR target/24615
index 3e417b5..19d874b 100644 (file)
   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;
+})
 \f
 ;; Call-value patterns last so that the wildcard operand does not
 ;; disrupt insn-recog's switch tables.
index 5fee48f..058fcb3 100644 (file)
@@ -1,3 +1,8 @@
+2005-11-02  Jan Hubicka  <jh@suse.cz>
+
+       PR target/23303
+       * gcc.dg/i386-lea.c: New test
+
 2005-11-02  Ulrich Weigand  <uweigand@de.ibm.com>
 
        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 (file)
index 0000000..61d9955
--- /dev/null
@@ -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];
+}