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:
parent
357d956ebd
commit
396b535a72
13 changed files with 356 additions and 2 deletions
|
@ -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
|
||||
|
|
|
@ -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))"))))
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
208
gcc/config/sparc/sync.md
Normal 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")])
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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'. */
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue