]> gcc.gnu.org Git - gcc.git/commitdiff
backport: sync.md: New file.
authorJakub Jelinek <jakub@redhat.com>
Tue, 3 Jan 2006 09:06:36 +0000 (10:06 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 3 Jan 2006 09:06:36 +0000 (10:06 +0100)
Merge from gomp-branch.
* config/sparc/sync.md: New file.
* config/sparc/sparc.md (UNSPECV_MEMBAR, UNSPECV_CAS, UNSPECV_SWAP,
UNSPECV_LDSTUB): New constants.
* config/sparc/sparc.c (sparc_expand_compare_and_swap_12): New function.
* config/sparc/predicates.md (memory_reg_operand): New predicate.
* config/sparc/sparc-protos.h (sparc_expand_compare_and_swap_12): New
prototype.

* gcc.dg/ia64-sync-1.c: On sparc*-*-*, pass -mcpu=v9.
* gcc.dg/ia64-sync-2.c: Likewise.
* gcc.dg/ia64-sync-3.c: Likewise.
* gcc.dg/ia64-sync-4.c: Likewise.
* gcc.dg/sync-2.c: Likewise.
* lib/target-supports.exp (sync_char_short, sync_int_long): Indicate
that sparc64-*-* and sparcv9-*-* supports sync builtins.

From-SVN: r109271

13 files changed:
gcc/ChangeLog
gcc/config/sparc/predicates.md
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.md
gcc/config/sparc/sync.md [new file with mode: 0644]
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ia64-sync-1.c
gcc/testsuite/gcc.dg/ia64-sync-2.c
gcc/testsuite/gcc.dg/ia64-sync-3.c
gcc/testsuite/gcc.dg/ia64-sync-4.c
gcc/testsuite/gcc.dg/sync-2.c
gcc/testsuite/lib/target-supports.exp

index 2aaeb5342f20c7d9f023d4b95f3617fafbe36539..dd9feb59d05275eb497727bda7c79cb451cbf86b 100644 (file)
@@ -1,3 +1,14 @@
+2006-01-03  Jakub Jelinek  <jakub@redhat.com>
+
+       Merge from gomp-branch.
+       * config/sparc/sync.md: New file.
+       * config/sparc/sparc.md (UNSPECV_MEMBAR, UNSPECV_CAS, UNSPECV_SWAP,
+       UNSPECV_LDSTUB): New constants.
+       * config/sparc/sparc.c (sparc_expand_compare_and_swap_12): New function.
+       * config/sparc/predicates.md (memory_reg_operand): New predicate.
+       * config/sparc/sparc-protos.h (sparc_expand_compare_and_swap_12): New
+       prototype.
+
 2006-01-03  Roger Sayle  <roger@eyesopen.com>
 
        * combine.c (reg_subword_p): New predicate to test whether the
index 6754a6de10b8cf79afe1003bb005639999431f35..048d651c2e57a8fa6937a92997a3a0374e4408d0 100644 (file)
 ;; and (xor ... (not ...)) to (not (xor ...)).  */
 (define_predicate "cc_arith_not_operator"
   (match_code "and,ior"))
+
+;; Return true if OP is memory operand with just [%reg] addressing mode.
+(define_predicate "memory_reg_operand"
+  (and (match_code "mem")
+       (and (match_operand 0 "memory_operand")
+           (match_test "REG_P (XEXP (op, 0))"))))
index 08d6171a5688b52d83eed4ca750390791bb3c281..4fb862cc9081cf462b3d215c3f1255fb53683cc9 100644 (file)
@@ -114,6 +114,7 @@ extern int v9_regcmp_p (enum rtx_code);
 extern int sparc_check_64 (rtx, rtx);
 extern rtx gen_df_reg (rtx, int);
 extern int sparc_extra_constraint_check (rtx, int, int);
+extern void sparc_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
 #endif /* RTX_CODE */
 
 #endif /* __SPARC_PROTOS_H__ */
index 52d2695d40f48c4d64cffcc5d55e7b547738acca..59ff2e17b861a58f9eeb12d623165acc19011c91 100644 (file)
@@ -8710,4 +8710,106 @@ sparc_file_end (void)
     file_end_indicate_exec_stack ();
 }
 
+/* Expand code to perform a 8 or 16-bit compare and swap by doing 32-bit
+   compare and swap on the word containing the byte or half-word.  */
+
+void
+sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
+{
+  rtx addr1 = force_reg (Pmode, XEXP (mem, 0));
+  rtx addr = gen_reg_rtx (Pmode);
+  rtx off = gen_reg_rtx (SImode);
+  rtx oldv = gen_reg_rtx (SImode);
+  rtx newv = gen_reg_rtx (SImode);
+  rtx oldvalue = gen_reg_rtx (SImode);
+  rtx newvalue = gen_reg_rtx (SImode);
+  rtx res = gen_reg_rtx (SImode);
+  rtx resv = gen_reg_rtx (SImode);
+  rtx memsi, val, mask, end_label, loop_label, cc;
+
+  emit_insn (gen_rtx_SET (VOIDmode, addr,
+                         gen_rtx_AND (Pmode, addr1, GEN_INT (-4))));
+
+  if (Pmode != SImode)
+    addr1 = gen_lowpart (SImode, addr1);
+  emit_insn (gen_rtx_SET (VOIDmode, off,
+                         gen_rtx_AND (SImode, addr1, GEN_INT (3))));
+
+  memsi = gen_rtx_MEM (SImode, addr);
+  MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem);
+
+  val = force_reg (SImode, memsi);
+
+  emit_insn (gen_rtx_SET (VOIDmode, off,
+                         gen_rtx_XOR (SImode, off,
+                                      GEN_INT (GET_MODE (mem) == QImode
+                                               ? 3 : 2))));
+
+  emit_insn (gen_rtx_SET (VOIDmode, off,
+                         gen_rtx_ASHIFT (SImode, off, GEN_INT (3))));
+
+  if (GET_MODE (mem) == QImode)
+    mask = force_reg (SImode, GEN_INT (0xff));
+  else
+    mask = force_reg (SImode, GEN_INT (0xffff));
+
+  emit_insn (gen_rtx_SET (VOIDmode, mask,
+                         gen_rtx_ASHIFT (SImode, mask, off)));
+
+  emit_insn (gen_rtx_SET (VOIDmode, val,
+                         gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
+                                      val)));
+
+  oldval = gen_lowpart (SImode, oldval);
+  emit_insn (gen_rtx_SET (VOIDmode, oldv,
+                         gen_rtx_ASHIFT (SImode, oldval, off)));
+
+  newval = gen_lowpart_common (SImode, newval);
+  emit_insn (gen_rtx_SET (VOIDmode, newv,
+                         gen_rtx_ASHIFT (SImode, newval, off)));
+
+  emit_insn (gen_rtx_SET (VOIDmode, oldv,
+                         gen_rtx_AND (SImode, oldv, mask)));
+
+  emit_insn (gen_rtx_SET (VOIDmode, newv,
+                         gen_rtx_AND (SImode, newv, mask)));
+
+  end_label = gen_label_rtx ();
+  loop_label = gen_label_rtx ();
+  emit_label (loop_label);
+
+  emit_insn (gen_rtx_SET (VOIDmode, oldvalue,
+                         gen_rtx_IOR (SImode, oldv, val)));
+
+  emit_insn (gen_rtx_SET (VOIDmode, newvalue,
+                         gen_rtx_IOR (SImode, newv, val)));
+
+  emit_insn (gen_sync_compare_and_swapsi (res, memsi, oldvalue, newvalue));
+
+  emit_cmp_and_jump_insns (res, oldvalue, EQ, NULL, SImode, 0, end_label);
+
+  emit_insn (gen_rtx_SET (VOIDmode, resv,
+                         gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
+                                      res)));
+
+  sparc_compare_op0 = resv;
+  sparc_compare_op1 = val;
+  cc = gen_compare_reg (NE);
+
+  emit_insn (gen_rtx_SET (VOIDmode, val, resv));
+
+  sparc_compare_emitted = cc;
+  emit_jump_insn (gen_bne (loop_label));
+
+  emit_label (end_label);
+
+  emit_insn (gen_rtx_SET (VOIDmode, res,
+                         gen_rtx_AND (SImode, res, mask)));
+
+  emit_insn (gen_rtx_SET (VOIDmode, res,
+                         gen_rtx_LSHIFTRT (SImode, res, off)));
+
+  emit_move_insn (result, gen_lowpart (GET_MODE (result), res));
+}
+
 #include "gt-sparc.h"
index 2047cfa2ddbac368c3d1f3f98791013e741e79b9..10727cb3416cc1e7dc84859a29867c32e044182a 100644 (file)
    (UNSPECV_FLUSH              4)
    (UNSPECV_SETJMP             5)
    (UNSPECV_SAVEW              6)
+   (UNSPECV_MEMBAR             7)
+   (UNSPECV_CAS                        8)
+   (UNSPECV_SWAP               9)
+   (UNSPECV_LDSTUB             10)
   ])
 
 ;; The upper 32 fp regs on the v9 can't hold SFmode values.  To deal with this
   "pdist\t%1, %2, %0"
   [(set_attr "type" "fga")
    (set_attr "fptype" "double")])
+
+(include "sync.md")
diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md
new file mode 100644 (file)
index 0000000..1337921
--- /dev/null
@@ -0,0 +1,208 @@
+;; GCC machine description for SPARC synchronization instructions.
+;; Copyright (C) 2005
+;; Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_mode_macro I12MODE [QI HI])
+(define_mode_macro I24MODE [HI SI])
+(define_mode_macro I48MODE [SI (DI "TARGET_ARCH64 || TARGET_V8PLUS")])
+(define_mode_attr modesuffix [(SI "") (DI "x")])
+
+(define_expand "memory_barrier"
+  [(set (mem:BLK (match_dup 0))
+       (unspec_volatile:BLK [(mem:BLK (match_dup 0)) (match_dup 1)]
+                            UNSPECV_MEMBAR))]
+  "TARGET_V8 || TARGET_V9"
+{
+  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
+  MEM_VOLATILE_P (operands[0]) = 1;
+  if (TARGET_V9)
+    /* member #StoreStore | #LoadStore | #StoreLoad | #LoadLoad */
+    operands[1] = GEN_INT (15);
+  else
+    /* stbar */
+    operands[1] = GEN_INT (8);
+})
+
+(define_insn "*stbar"
+  [(set (match_operand:BLK 0 "" "")
+       (unspec_volatile:BLK [(match_operand:BLK 1 "" "")
+                             (const_int 8)] UNSPECV_MEMBAR))]
+  "TARGET_V8"
+  "stbar"
+  [(set_attr "type" "multi")])
+
+(define_insn "*membar"
+  [(set (match_operand:BLK 0 "" "")
+       (unspec_volatile:BLK [(match_operand:BLK 1 "" "")
+                             (match_operand:SI 2 "immediate_operand" "I")]
+                             UNSPECV_MEMBAR))]
+  "TARGET_V9"
+  "membar\t%2"
+  [(set_attr "type" "multi")])
+
+(define_expand "sync_compare_and_swap<mode>"
+  [(match_operand:I12MODE 0 "register_operand" "")
+   (match_operand:I12MODE 1 "memory_operand" "")
+   (match_operand:I12MODE 2 "register_operand" "")
+   (match_operand:I12MODE 3 "register_operand" "")]
+  "TARGET_V9"
+{
+  sparc_expand_compare_and_swap_12 (operands[0], operands[1],
+                                   operands[2], operands[3]);
+  DONE;
+})
+
+(define_expand "sync_compare_and_swap<mode>"
+  [(parallel
+     [(set (match_operand:I48MODE 0 "register_operand" "=r")
+          (match_operand:I48MODE 1 "memory_operand" ""))
+      (set (match_dup 1)
+          (unspec_volatile:I48MODE
+            [(match_operand:I48MODE 2 "register_operand" "")
+             (match_operand:I48MODE 3 "register_operand" "")]
+            UNSPECV_CAS))])]
+  "TARGET_V9"
+{
+  if (! REG_P (XEXP (operands[1], 0)))
+    {
+      rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
+      operands[1] = replace_equiv_address (operands[1], addr);
+    }
+  emit_insn (gen_memory_barrier ());
+})
+
+(define_insn "*sync_compare_and_swap<mode>"
+  [(set (match_operand:I48MODE 0 "register_operand" "=r")
+       (match_operand:I48MODE 1 "memory_reg_operand" "+m"))
+   (set (match_dup 1)
+       (unspec_volatile:I48MODE
+         [(match_operand:I48MODE 2 "register_operand" "r")
+          (match_operand:I48MODE 3 "register_operand" "0")]
+         UNSPECV_CAS))]
+  "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
+  "cas<modesuffix>\t%1, %2, %0"
+  [(set_attr "type" "multi")])
+
+(define_insn "*sync_compare_and_swapdi_v8plus"
+  [(set (match_operand:DI 0 "register_operand" "=h")
+       (match_operand:DI 1 "memory_reg_operand" "+m"))
+   (set (match_dup 1)
+       (unspec_volatile:DI
+         [(match_operand:DI 2 "register_operand" "h")
+          (match_operand:DI 3 "register_operand" "0")]
+         UNSPECV_CAS))]
+  "TARGET_V8PLUS"
+{
+  if (sparc_check_64 (operands[3], insn) <= 0)
+    output_asm_insn ("srl\t%L3, 0, %L3", operands);
+  output_asm_insn ("sllx\t%H3, 32, %H3", operands);
+  output_asm_insn ("or\t%L3, %H3, %L3", operands);
+  if (sparc_check_64 (operands[2], insn) <= 0)
+    output_asm_insn ("srl\t%L2, 0, %L2", operands);
+  output_asm_insn ("sllx\t%H2, 32, %H3", operands);
+  output_asm_insn ("or\t%L2, %H3, %H3", operands);
+  output_asm_insn ("casx\t%1, %H3, %L3", operands);
+  return "srlx\t%L3, 32, %H3";
+}
+  [(set_attr "type" "multi")
+   (set_attr "length" "8")])
+
+(define_expand "sync_lock_test_and_set<mode>"
+  [(match_operand:I12MODE 0 "register_operand" "")
+   (match_operand:I12MODE 1 "memory_operand" "")
+   (match_operand:I12MODE 2 "arith_operand" "")]
+  "!TARGET_V9"
+{
+  if (operands[2] != const1_rtx)
+    FAIL;
+  if (TARGET_V8)
+    emit_insn (gen_memory_barrier ());
+  if (<MODE>mode != QImode)
+    operands[1] = adjust_address (operands[1], QImode, 0);
+  emit_insn (gen_ldstub<mode> (operands[0], operands[1]));
+  DONE;
+})
+
+(define_expand "sync_lock_test_and_setsi"
+  [(parallel
+     [(set (match_operand:SI 0 "register_operand" "")
+          (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "")]
+                              UNSPECV_SWAP))
+      (set (match_dup 1)
+          (match_operand:SI 2 "arith_operand" ""))])]
+  ""
+{
+  if (! TARGET_V8 && ! TARGET_V9)
+    {
+      if (operands[2] != const1_rtx)
+       FAIL;
+      operands[1] = adjust_address (operands[1], QImode, 0);
+      emit_insn (gen_ldstubsi (operands[0], operands[1]));
+      DONE;
+    }
+  emit_insn (gen_memory_barrier ());
+  operands[2] = force_reg (SImode, operands[2]);
+})
+
+(define_insn "*swapsi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "+m")]
+                           UNSPECV_SWAP))
+   (set (match_dup 1)
+       (match_operand:SI 2 "register_operand" "0"))]
+  "TARGET_V8 || TARGET_V9"
+  "swap\t%1, %0"
+  [(set_attr "type" "multi")])
+
+(define_expand "ldstubqi"
+  [(parallel [(set (match_operand:QI 0 "register_operand" "")
+                  (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
+                                      UNSPECV_LDSTUB))
+             (set (match_dup 1) (const_int -1))])]
+  ""
+  "")
+
+(define_expand "ldstub<mode>"
+  [(parallel [(set (match_operand:I24MODE 0 "register_operand" "")
+                  (zero_extend:I24MODE
+                     (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
+                                         UNSPECV_LDSTUB)))
+             (set (match_dup 1) (const_int -1))])]
+  ""
+  "")
+
+(define_insn "*ldstubqi"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
+                           UNSPECV_LDSTUB))
+   (set (match_dup 1) (const_int -1))]
+  ""
+  "ldstub\t%1, %0"
+  [(set_attr "type" "multi")])
+
+(define_insn "*ldstub<mode>"
+  [(set (match_operand:I24MODE 0 "register_operand" "=r")
+       (zero_extend:I24MODE
+         (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
+                             UNSPECV_LDSTUB)))
+   (set (match_dup 1) (const_int -1))]
+  ""
+  "ldstub\t%1, %0"
+  [(set_attr "type" "multi")])
index f96ba05f169699620e9bc2b71aaddefc94beafc8..1acf301b8de62baf93b1e281d6312830694fa056 100644 (file)
@@ -1,3 +1,14 @@
+2006-01-03  Jakub Jelinek  <jakub@redhat.com>
+
+       Merge from gomp-branch.
+       * gcc.dg/ia64-sync-1.c: On sparc*-*-*, pass -mcpu=v9.
+       * gcc.dg/ia64-sync-2.c: Likewise.
+       * gcc.dg/ia64-sync-3.c: Likewise.
+       * gcc.dg/ia64-sync-4.c: Likewise.
+       * gcc.dg/sync-2.c: Likewise.
+       * lib/target-supports.exp (sync_char_short, sync_int_long): Indicate
+       that sparc64-*-* and sparcv9-*-* supports sync builtins.
+
 2006-01-02  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/25635
index af1411c81a88042a4b40df51e2ea4b83d616eeb5..8f4512e4fbfdf3f3938b81435af39d1371776384 100644 (file)
@@ -2,6 +2,7 @@
 /* { dg-require-effective-target sync_int_long } */
 /* { dg-options } */
 /* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
 
 /* Test basic functionality of the intrinsics.  The operations should
    not be optimized away if no one checks the return values.  */
index 73e793f91c728db14347f7335461711927bdcf5a..bb8c728bea38d265a4d40dc7671c6e2334af4bcf 100644 (file)
@@ -2,6 +2,7 @@
 /* { dg-require-effective-target sync_int_long } */
 /* { dg-options } */
 /* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
 
 /* Test basic functionality of the intrinsics.  */
 
index 9e8d40c91687e9ac94d8eaf87fef12ae59238f86..d093cdd4cb19075947ef68703161d68f88a9ca38 100644 (file)
@@ -2,6 +2,7 @@
 /* { dg-require-effective-target sync_int_long } */
 /* { dg-options } */
 /* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
 
 /* Test basic functionality of the intrinsics.  */
 
index 8cd3940a89c101bdae53f9dbb27bdde2f21b3939..e78fb4cf82529f7139f04f458c1aa4818265b56d 100644 (file)
@@ -2,6 +2,7 @@
 /* { dg-require-effective-target sync_int_long } */
 /* { dg-options "-O2 -finline-functions" } */
 /* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
 
 /* Test inlining __sync_bool_compare_and_swap.  */
 
index ab2e27632a1fc02c627c06f0c0acdf5378d13eb4..c82d66521ca1edb2b3e67433e816e27ebbced76e 100644 (file)
@@ -1,6 +1,7 @@
 /* { dg-do run } */
 /* { dg-require-effective-target sync_char_short } */
 /* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
 
 /* Test functionality of the intrinsics for 'short' and 'char'.  */
 
index edafc749b52264bfca3c4183872ad42b87bc9fad..2e91a161eeb84772651e65fe3b82237d15217b7d 100644 (file)
@@ -1356,7 +1356,9 @@ proc check_effective_target_sync_int_long { } {
             || [istarget x86_64-*-*]
             || [istarget alpha*-*-*] 
             || [istarget s390*-*-*] 
-            || [istarget powerpc*-*-*] } {
+            || [istarget powerpc*-*-*]
+            || [istarget sparc64-*-*]
+            || [istarget sparcv9-*-*] } {
            set et_sync_int_long_saved 1
         }
     }
@@ -1381,7 +1383,9 @@ proc check_effective_target_sync_char_short { } {
             || [istarget x86_64-*-*]
             || [istarget alpha*-*-*] 
             || [istarget s390*-*-*] 
-            || [istarget powerpc*-*-*] } {
+            || [istarget powerpc*-*-*]
+            || [istarget sparc64-*-*]
+            || [istarget sparcv9-*-*] } {
            set et_sync_char_short_saved 1
         }
     }
This page took 0.095871 seconds and 5 git commands to generate.