From: Jakub Jelinek Date: Tue, 3 Jan 2006 09:06:36 +0000 (+0100) Subject: backport: sync.md: New file. X-Git-Tag: releases/gcc-4.2.0~5068 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=396b535a72eb44422b3b8f0f1c220b11ab34b24d;p=gcc.git backport: sync.md: New file. 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2aaeb5342f20..dd9feb59d052 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2006-01-03 Jakub Jelinek + + 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 * combine.c (reg_subword_p): New predicate to test whether the diff --git a/gcc/config/sparc/predicates.md b/gcc/config/sparc/predicates.md index 6754a6de10b8..048d651c2e57 100644 --- a/gcc/config/sparc/predicates.md +++ b/gcc/config/sparc/predicates.md @@ -470,3 +470,9 @@ ;; 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))")))) diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index 08d6171a5688..4fb862cc9081 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -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__ */ diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 52d2695d40f4..59ff2e17b861 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -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" diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 2047cfa2ddba..10727cb3416c 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -69,6 +69,10 @@ (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 @@ -8476,3 +8480,5 @@ "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 index 000000000000..133792127e5c --- /dev/null +++ b/gcc/config/sparc/sync.md @@ -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" + [(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" + [(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" + [(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 == SImode || TARGET_ARCH64)" + "cas\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" + [(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 != QImode) + operands[1] = adjust_address (operands[1], QImode, 0); + emit_insn (gen_ldstub (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" + [(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" + [(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")]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f96ba05f1696..1acf301b8de6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2006-01-03 Jakub Jelinek + + 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 PR c++/25635 diff --git a/gcc/testsuite/gcc.dg/ia64-sync-1.c b/gcc/testsuite/gcc.dg/ia64-sync-1.c index af1411c81a88..8f4512e4fbfd 100644 --- a/gcc/testsuite/gcc.dg/ia64-sync-1.c +++ b/gcc/testsuite/gcc.dg/ia64-sync-1.c @@ -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. */ diff --git a/gcc/testsuite/gcc.dg/ia64-sync-2.c b/gcc/testsuite/gcc.dg/ia64-sync-2.c index 73e793f91c72..bb8c728bea38 100644 --- a/gcc/testsuite/gcc.dg/ia64-sync-2.c +++ b/gcc/testsuite/gcc.dg/ia64-sync-2.c @@ -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. */ diff --git a/gcc/testsuite/gcc.dg/ia64-sync-3.c b/gcc/testsuite/gcc.dg/ia64-sync-3.c index 9e8d40c91687..d093cdd4cb19 100644 --- a/gcc/testsuite/gcc.dg/ia64-sync-3.c +++ b/gcc/testsuite/gcc.dg/ia64-sync-3.c @@ -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. */ diff --git a/gcc/testsuite/gcc.dg/ia64-sync-4.c b/gcc/testsuite/gcc.dg/ia64-sync-4.c index 8cd3940a89c1..e78fb4cf8252 100644 --- a/gcc/testsuite/gcc.dg/ia64-sync-4.c +++ b/gcc/testsuite/gcc.dg/ia64-sync-4.c @@ -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. */ diff --git a/gcc/testsuite/gcc.dg/sync-2.c b/gcc/testsuite/gcc.dg/sync-2.c index ab2e27632a1f..c82d66521ca1 100644 --- a/gcc/testsuite/gcc.dg/sync-2.c +++ b/gcc/testsuite/gcc.dg/sync-2.c @@ -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'. */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index edafc749b522..2e91a161eeb8 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -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 } }