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
This commit is contained in:
Jakub Jelinek 2006-01-03 10:06:36 +01:00 committed by Jakub Jelinek
parent 357d956ebd
commit 396b535a72
13 changed files with 356 additions and 2 deletions

View 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

View file

@ -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))"))))

View 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__ */

View 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"

View file

@ -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")

208
gcc/config/sparc/sync.md Normal file
View file

@ -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")])

View 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

View 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. */

View 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. */

View 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. */

View 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. */

View 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'. */

View 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
}
}