OSDN Git Service

PR target/39431
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Mar 2009 20:45:39 +0000 (20:45 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Mar 2009 20:45:39 +0000 (20:45 +0000)
* config/i386/predicates.md (cmpxchg8b_pic_memory_operand): New
predicate.
* config/i386/sync.md (sync_compare_and_swap<mode>,
sync_compare_and_swap_cc<mode>): For DImode with -m32 -fpic check
if operands[1] is cmpxchg8b_pic_memory_operand, if not force address
into a register.
(sync_double_compare_and_swapdi_pic,
sync_double_compare_and_swap_ccdi_pic): Require operand 1 to be
cmpxchg8b_pic_memory_operand instead of just memory_operand.

* gcc.target/i386/pr39431.c: New test.

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

gcc/ChangeLog
gcc/config/i386/predicates.md
gcc/config/i386/sync.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr39431.c [new file with mode: 0644]

index 9c17490..2282b89 100644 (file)
@@ -1,3 +1,16 @@
+2008-03-12  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/39431
+       * config/i386/predicates.md (cmpxchg8b_pic_memory_operand): New
+       predicate.
+       * config/i386/sync.md (sync_compare_and_swap<mode>,
+       sync_compare_and_swap_cc<mode>): For DImode with -m32 -fpic check
+       if operands[1] is cmpxchg8b_pic_memory_operand, if not force address
+       into a register.
+       (sync_double_compare_and_swapdi_pic,
+       sync_double_compare_and_swap_ccdi_pic): Require operand 1 to be
+       cmpxchg8b_pic_memory_operand instead of just memory_operand.
+
 2009-03-12  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/39445
index b2bef64..f1c7103 100644 (file)
   return parts.disp != NULL_RTX;
 })
 
+;; Returns 1 if OP is memory operand which will need zero or
+;; one register at most, not counting stack pointer or frame pointer.
+(define_predicate "cmpxchg8b_pic_memory_operand"
+  (match_operand 0 "memory_operand")
+{
+  struct ix86_address parts;
+  int ok;
+
+  ok = ix86_decompose_address (XEXP (op, 0), &parts);
+  gcc_assert (ok);
+  if (parts.base == NULL_RTX
+      || parts.base == arg_pointer_rtx
+      || parts.base == frame_pointer_rtx
+      || parts.base == hard_frame_pointer_rtx
+      || parts.base == stack_pointer_rtx)
+    return 1;
+
+  if (parts.index == NULL_RTX
+      || parts.index == arg_pointer_rtx
+      || parts.index == frame_pointer_rtx
+      || parts.index == hard_frame_pointer_rtx
+      || parts.index == stack_pointer_rtx)
+    return 1;
+
+  return 0;
+})
+
+
 ;; Returns 1 if OP is memory operand that cannot be represented
 ;; by the modRM array.
 (define_predicate "long_memory_operand"
index e267574..05aad00 100644 (file)
@@ -1,5 +1,5 @@
 ;; GCC machine description for i386 synchronization instructions.
-;; Copyright (C) 2005, 2006, 2007, 2008
+;; Copyright (C) 2005, 2006, 2007, 2008, 2009
 ;; Free Software Foundation, Inc.
 ;;
 ;; This file is part of GCC.
       low = force_reg (hmode, low);
       high = force_reg (hmode, high);
       if (<MODE>mode == DImode)
-       emit_insn (gen_sync_double_compare_and_swapdi
-                  (operands[0], operands[1], operands[2], low, high));
+       {
+         if (flag_pic && !cmpxchg8b_pic_memory_operand (operands[1], DImode))
+           operands[1] = replace_equiv_address (operands[1],
+                                                force_reg (Pmode,
+                                                           XEXP (operands[1],
+                                                                 0)));
+         emit_insn (gen_sync_double_compare_and_swapdi
+                    (operands[0], operands[1], operands[2], low, high));
+       }
       else if (<MODE>mode == TImode)
        emit_insn (gen_sync_double_compare_and_swapti
                   (operands[0], operands[1], operands[2], low, high));
 ;; are just esi and edi.
 (define_insn "*sync_double_compare_and_swapdi_pic"
   [(set (match_operand:DI 0 "register_operand" "=A")
-       (match_operand:DI 1 "memory_operand" "+m"))
+       (match_operand:DI 1 "cmpxchg8b_pic_memory_operand" "+m"))
    (set (match_dup 1)
        (unspec_volatile:DI
          [(match_dup 1)
       low = force_reg (hmode, low);
       high = force_reg (hmode, high);
       if (<MODE>mode == DImode)
-       emit_insn (gen_sync_double_compare_and_swap_ccdi
-                  (operands[0], operands[1], operands[2], low, high));
+       {
+         if (flag_pic && !cmpxchg8b_pic_memory_operand (operands[1], DImode))
+           operands[1] = replace_equiv_address (operands[1],
+                                                force_reg (Pmode,
+                                                           XEXP (operands[1],
+                                                                 0)));
+         emit_insn (gen_sync_double_compare_and_swap_ccdi
+                    (operands[0], operands[1], operands[2], low, high));
+       }
       else if (<MODE>mode == TImode)
        emit_insn (gen_sync_double_compare_and_swap_ccti
                   (operands[0], operands[1], operands[2], low, high));
 ;; operand 3.
 (define_insn "*sync_double_compare_and_swap_ccdi_pic"
   [(set (match_operand:DI 0 "register_operand" "=A")
-       (match_operand:DI 1 "memory_operand" "+m"))
+       (match_operand:DI 1 "cmpxchg8b_pic_memory_operand" "+m"))
    (set (match_dup 1)
        (unspec_volatile:DI
          [(match_dup 1)
index 8c9a362..1940fe5 100644 (file)
@@ -1,3 +1,8 @@
+2008-03-12  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/39431
+       * gcc.target/i386/pr39431.c: New test.
+
 2009-03-12  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/39445
diff --git a/gcc/testsuite/gcc.target/i386/pr39431.c b/gcc/testsuite/gcc.target/i386/pr39431.c
new file mode 100644 (file)
index 0000000..756bdb9
--- /dev/null
@@ -0,0 +1,15 @@
+/* PR target/39431 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-options "-O2 -march=i686 -fpic" { target { ilp32 && fpic } } } */
+
+extern void bar (char *, int);
+
+int
+foo (long long *p, long long oldv, long long *q, int n)
+{
+  char buf[n];
+  bar (buf, n);
+  p[256 + n] = __sync_val_compare_and_swap (p + n, oldv, oldv + 6);
+  return __sync_bool_compare_and_swap (q + n, oldv, oldv + 8);
+}