alpha.c (emit_insxl, [...]): New functions.

* config/alpha/alpha.c (emit_insxl, alpha_expand_compare_and_swap_12,
        alpha_split_compare_and_swap_12, alpha_expand_lock_test_and_set_12,
        alpha_split_lock_test_and_set_12): New functions.
        * config/alpha/alpha-protos.h: Update.
        * config/alpha/alpha.md (UNSPEC_MB, UNSPEC_ATOMIC,
        UNSPEC_CMPXCHG, UNSPEC_XCHG): Rename from UNSPECV_FOO.
        * config/alpha/sync.md (I12MODE): New.
        (memory_barrier, mb_internal): Use unspec instead of unspec_volatile.
        (sync_<fetchop_name><I48MODE>): Likewise.
        (sync_nand<I48MODE>): Likewise.
        (sync_old_<fetchop_name><I48MODE>): Likewise.
        (sync_new_<fetchop_name><I48MODE>): Likewise.
        (sync_old_nand<I48MODE>, sync_new_nand<I48MODE>): Likewise.
        (sync_compare_and_swap<I48MODE>): Likewise.
        (sync_lock_test_and_set<I48MODE>): Likewise.
        (sync_compare_and_swap<I12MODE>): New.
        (sync_compare_and_swap<I12MODE>_1): New.
        (sync_lock_test_and_set<I12MODE>): New.
        (sync_lock_test_and_set<I12MODE>_1): New.

        * lib/target-supports.exp (check_effective_target_sync_char_short):
        Add alpha.

From-SVN: r101833
This commit is contained in:
Richard Henderson 2005-07-09 11:28:23 -07:00
parent 563cb6be0f
commit 38f3168781
7 changed files with 294 additions and 28 deletions

View File

@ -1,9 +1,30 @@
2005-07-09 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.c (emit_insxl, alpha_expand_compare_and_swap_12,
alpha_split_compare_and_swap_12, alpha_expand_lock_test_and_set_12,
alpha_split_lock_test_and_set_12): New functions.
* config/alpha/alpha-protos.h: Update.
* config/alpha/alpha.md (UNSPEC_MB, UNSPEC_ATOMIC,
UNSPEC_CMPXCHG, UNSPEC_XCHG): Rename from UNSPECV_FOO.
* config/alpha/sync.md (I12MODE): New.
(memory_barrier, mb_internal): Use unspec instead of unspec_volatile.
(sync_<fetchop_name><I48MODE>): Likewise.
(sync_nand<I48MODE>): Likewise.
(sync_old_<fetchop_name><I48MODE>): Likewise.
(sync_new_<fetchop_name><I48MODE>): Likewise.
(sync_old_nand<I48MODE>, sync_new_nand<I48MODE>): Likewise.
(sync_compare_and_swap<I48MODE>): Likewise.
(sync_lock_test_and_set<I48MODE>): Likewise.
(sync_compare_and_swap<I12MODE>): New.
(sync_compare_and_swap<I12MODE>_1): New.
(sync_lock_test_and_set<I12MODE>): New.
(sync_lock_test_and_set<I12MODE>_1): New.
2005-07-09 Diego Novillo <dnovillo@redhat.com>
PR 21356
PR 22332
* passes.c (execute_todo): Cleanup the CFG before updating
SSA.
* passes.c (execute_todo): Cleanup the CFG before updating SSA.
2005-07-09 Jakub Jelinek <jakub@redhat.com>

View File

@ -103,7 +103,13 @@ extern void alpha_emit_xfloating_arith (enum rtx_code, rtx[]);
extern void alpha_emit_xfloating_cvt (enum rtx_code, rtx[]);
extern void alpha_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
extern void alpha_split_compare_and_swap (rtx, rtx, rtx, rtx, rtx);
extern void alpha_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
extern void alpha_split_compare_and_swap_12 (enum machine_mode, rtx, rtx,
rtx, rtx, rtx, rtx, rtx);
extern void alpha_split_lock_test_and_set (rtx, rtx, rtx, rtx);
extern void alpha_expand_lock_test_and_set_12 (rtx, rtx, rtx);
extern void alpha_split_lock_test_and_set_12 (enum machine_mode, rtx, rtx,
rtx, rtx, rtx);
#endif
extern rtx alpha_need_linkage (const char *, int);

View File

@ -4453,6 +4453,34 @@ emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
emit_insn (fn (res, mem, val));
}
/* A subroutine of the atomic operation splitters. Emit an insxl
instruction in MODE. */
static rtx
emit_insxl (enum machine_mode mode, rtx op1, rtx op2)
{
rtx ret = gen_reg_rtx (DImode);
rtx (*fn) (rtx, rtx, rtx);
if (WORDS_BIG_ENDIAN)
{
if (mode == QImode)
fn = gen_insbl_be;
else
fn = gen_inswl_be;
}
else
{
if (mode == QImode)
fn = gen_insbl_le;
else
fn = gen_inswl_le;
}
emit_insn (fn (ret, op1, op2));
return ret;
}
/* Expand an an atomic fetch-and-operate pattern. CODE is the binary operation
to perform. MEM is the memory on which to operate. VAL is the second
operand of the binary operator. BEFORE and AFTER are optional locations to
@ -4530,6 +4558,79 @@ alpha_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
emit_label (XEXP (label2, 0));
}
void
alpha_expand_compare_and_swap_12 (rtx dst, rtx mem, rtx oldval, rtx newval)
{
enum machine_mode mode = GET_MODE (mem);
rtx addr, align, wdst;
rtx (*fn5) (rtx, rtx, rtx, rtx, rtx);
addr = force_reg (DImode, XEXP (mem, 0));
align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
NULL_RTX, 1, OPTAB_DIRECT);
oldval = convert_modes (DImode, mode, oldval, 1);
newval = emit_insxl (mode, newval, addr);
wdst = gen_reg_rtx (DImode);
if (mode == QImode)
fn5 = gen_sync_compare_and_swapqi_1;
else
fn5 = gen_sync_compare_and_swaphi_1;
emit_insn (fn5 (wdst, addr, oldval, newval, align));
emit_move_insn (dst, gen_lowpart (mode, wdst));
}
void
alpha_split_compare_and_swap_12 (enum machine_mode mode, rtx dest, rtx addr,
rtx oldval, rtx newval, rtx align,
rtx scratch, rtx cond)
{
rtx label1, label2, mem, width, mask, x;
mem = gen_rtx_MEM (DImode, align);
MEM_VOLATILE_P (mem) = 1;
emit_insn (gen_memory_barrier ());
label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
emit_label (XEXP (label1, 0));
emit_load_locked (DImode, scratch, mem);
width = GEN_INT (GET_MODE_BITSIZE (mode));
mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
if (WORDS_BIG_ENDIAN)
emit_insn (gen_extxl_be (dest, scratch, width, addr));
else
emit_insn (gen_extxl_le (dest, scratch, width, addr));
if (oldval == const0_rtx)
x = gen_rtx_NE (DImode, dest, const0_rtx);
else
{
x = gen_rtx_EQ (DImode, dest, oldval);
emit_insn (gen_rtx_SET (VOIDmode, cond, x));
x = gen_rtx_EQ (DImode, cond, const0_rtx);
}
emit_unlikely_jump (x, label2);
if (WORDS_BIG_ENDIAN)
emit_insn (gen_mskxl_be (scratch, scratch, mask, addr));
else
emit_insn (gen_mskxl_le (scratch, scratch, mask, addr));
emit_insn (gen_iordi3 (scratch, scratch, newval));
emit_store_conditional (DImode, scratch, mem, scratch);
x = gen_rtx_EQ (DImode, scratch, const0_rtx);
emit_unlikely_jump (x, label1);
emit_insn (gen_memory_barrier ());
emit_label (XEXP (label2, 0));
}
/* Expand an atomic exchange operation. */
void
@ -4550,6 +4651,68 @@ alpha_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
x = gen_rtx_EQ (DImode, cond, const0_rtx);
emit_unlikely_jump (x, label);
}
void
alpha_expand_lock_test_and_set_12 (rtx dst, rtx mem, rtx val)
{
enum machine_mode mode = GET_MODE (mem);
rtx addr, align, wdst;
rtx (*fn4) (rtx, rtx, rtx, rtx);
/* Force the address into a register. */
addr = force_reg (DImode, XEXP (mem, 0));
/* Align it to a multiple of 8. */
align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
NULL_RTX, 1, OPTAB_DIRECT);
/* Insert val into the correct byte location within the word. */
val = emit_insxl (mode, val, addr);
wdst = gen_reg_rtx (DImode);
if (mode == QImode)
fn4 = gen_sync_lock_test_and_setqi_1;
else
fn4 = gen_sync_lock_test_and_sethi_1;
emit_insn (fn4 (wdst, addr, val, align));
emit_move_insn (dst, gen_lowpart (mode, wdst));
}
void
alpha_split_lock_test_and_set_12 (enum machine_mode mode, rtx dest, rtx addr,
rtx val, rtx align, rtx scratch)
{
rtx label, mem, width, mask, x;
mem = gen_rtx_MEM (DImode, align);
MEM_VOLATILE_P (mem) = 1;
emit_insn (gen_memory_barrier ());
label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
emit_label (XEXP (label, 0));
emit_load_locked (DImode, scratch, mem);
width = GEN_INT (GET_MODE_BITSIZE (mode));
mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
if (WORDS_BIG_ENDIAN)
{
emit_insn (gen_extxl_be (dest, scratch, width, addr));
emit_insn (gen_mskxl_be (scratch, scratch, mask, addr));
}
else
{
emit_insn (gen_extxl_le (dest, scratch, width, addr));
emit_insn (gen_mskxl_le (scratch, scratch, mask, addr));
}
emit_insn (gen_iordi3 (scratch, scratch, val));
emit_store_conditional (DImode, scratch, mem, scratch);
x = gen_rtx_EQ (DImode, scratch, const0_rtx);
emit_unlikely_jump (x, label);
}
/* Adjust the cost of a scheduling dependency. Return the new cost of
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */

View File

@ -56,6 +56,12 @@
(UNSPEC_IMPLVER 25)
(UNSPEC_PERR 26)
(UNSPEC_COPYSIGN 27)
;; Atomic operations
(UNSPEC_MB 28)
(UNSPEC_ATOMIC 31)
(UNSPEC_CMPXCHG 32)
(UNSPEC_XCHG 33)
])
;; UNSPEC_VOLATILE:
@ -76,12 +82,8 @@
(UNSPECV_SET_TP 12)
(UNSPECV_RPCC 13)
(UNSPECV_SETJMPR_ER 14) ; builtin_setjmp_receiver fragment
(UNSPECV_MB 15)
(UNSPECV_LL 16) ; load-locked
(UNSPECV_SC 17) ; store-conditional
(UNSPECV_ATOMIC 18)
(UNSPECV_CMPXCHG 19)
(UNSPECV_XCHG 20)
(UNSPECV_LL 15) ; load-locked
(UNSPECV_SC 16) ; store-conditional
])
;; Where necessary, the suffixes _le and _be are used to distinguish between

View File

@ -19,6 +19,7 @@
;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
(define_mode_macro I12MODE [QI HI])
(define_mode_macro I48MODE [SI DI])
(define_mode_attr modesuffix [(SI "l") (DI "q")])
@ -34,7 +35,7 @@
(define_expand "memory_barrier"
[(set (mem:BLK (match_dup 0))
(unspec_volatile:BLK [(mem:BLK (match_dup 0))] UNSPECV_MB))]
(unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MB))]
""
{
operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
@ -43,7 +44,7 @@
(define_insn "*mb_internal"
[(set (match_operand:BLK 0 "" "")
(unspec_volatile:BLK [(match_operand:BLK 1 "" "")] UNSPECV_MB))]
(unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MB))]
""
"mb"
[(set_attr "type" "mb")])
@ -75,10 +76,10 @@
(define_insn_and_split "sync_<fetchop_name><mode>"
[(set (match_operand:I48MODE 0 "memory_operand" "+m")
(unspec_volatile:I48MODE
(unspec:I48MODE
[(FETCHOP:I48MODE (match_dup 0)
(match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>"))]
UNSPECV_ATOMIC))
UNSPEC_ATOMIC))
(clobber (match_scratch:I48MODE 2 "=&r"))]
""
"#"
@ -93,10 +94,10 @@
(define_insn_and_split "sync_nand<mode>"
[(set (match_operand:I48MODE 0 "memory_operand" "+m")
(unspec_volatile:I48MODE
(unspec:I48MODE
[(and:I48MODE (not:I48MODE (match_dup 0))
(match_operand:I48MODE 1 "register_operand" "r"))]
UNSPECV_ATOMIC))
UNSPEC_ATOMIC))
(clobber (match_scratch:I48MODE 2 "=&r"))]
""
"#"
@ -113,10 +114,10 @@
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
(match_operand:I48MODE 1 "memory_operand" "+m"))
(set (match_dup 1)
(unspec_volatile:I48MODE
(unspec:I48MODE
[(FETCHOP:I48MODE (match_dup 1)
(match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))]
UNSPECV_ATOMIC))
UNSPEC_ATOMIC))
(clobber (match_scratch:I48MODE 3 "=&r"))]
""
"#"
@ -133,10 +134,10 @@
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
(match_operand:I48MODE 1 "memory_operand" "+m"))
(set (match_dup 1)
(unspec_volatile:I48MODE
(unspec:I48MODE
[(and:I48MODE (not:I48MODE (match_dup 1))
(match_operand:I48MODE 2 "register_operand" "r"))]
UNSPECV_ATOMIC))
UNSPEC_ATOMIC))
(clobber (match_scratch:I48MODE 3 "=&r"))]
""
"#"
@ -155,9 +156,9 @@
(match_operand:I48MODE 1 "memory_operand" "+m")
(match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")))
(set (match_dup 1)
(unspec_volatile:I48MODE
(unspec:I48MODE
[(FETCHOP:I48MODE (match_dup 1) (match_dup 2))]
UNSPECV_ATOMIC))
UNSPEC_ATOMIC))
(clobber (match_scratch:I48MODE 3 "=&r"))]
""
"#"
@ -176,9 +177,9 @@
(not:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m"))
(match_operand:I48MODE 2 "register_operand" "r")))
(set (match_dup 1)
(unspec_volatile:I48MODE
(unspec:I48MODE
[(and:I48MODE (not:I48MODE (match_dup 1)) (match_dup 2))]
UNSPECV_ATOMIC))
UNSPEC_ATOMIC))
(clobber (match_scratch:I48MODE 3 "=&r"))]
""
"#"
@ -191,15 +192,51 @@
}
[(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 "add_operand" "")]
""
{
alpha_expand_compare_and_swap_12 (operands[0], operands[1],
operands[2], operands[3]);
DONE;
})
(define_insn_and_split "sync_compare_and_swap<mode>_1"
[(set (match_operand:DI 0 "register_operand" "=&r,&r")
(zero_extend:DI
(mem:I12MODE (match_operand:DI 1 "register_operand" "r,r"))))
(set (mem:I12MODE (match_dup 1))
(unspec:I12MODE
[(match_operand:DI 2 "reg_or_8bit_operand" "J,rI")
(match_operand:DI 3 "register_operand" "r,r")
(match_operand:DI 4 "register_operand" "r,r")]
UNSPEC_CMPXCHG))
(clobber (match_scratch:DI 5 "=&r,&r"))
(clobber (match_scratch:DI 6 "=X,&r"))]
""
"#"
"reload_completed"
[(const_int 0)]
{
alpha_split_compare_and_swap_12 (<MODE>mode, operands[0], operands[1],
operands[2], operands[3], operands[4],
operands[5], operands[6]);
DONE;
}
[(set_attr "type" "multi")])
(define_expand "sync_compare_and_swap<mode>"
[(parallel
[(set (match_operand:I48MODE 0 "register_operand" "")
(match_operand:I48MODE 1 "memory_operand" ""))
(set (match_dup 1)
(unspec_volatile:I48MODE
(unspec:I48MODE
[(match_operand:I48MODE 2 "reg_or_8bit_operand" "")
(match_operand:I48MODE 3 "add_operand" "rKL")]
UNSPECV_CMPXCHG))
UNSPEC_CMPXCHG))
(clobber (match_scratch:I48MODE 4 "=&r"))])]
""
{
@ -211,10 +248,10 @@
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
(match_operand:I48MODE 1 "memory_operand" "+m"))
(set (match_dup 1)
(unspec_volatile:I48MODE
(unspec:I48MODE
[(match_operand:DI 2 "reg_or_8bit_operand" "rI")
(match_operand:I48MODE 3 "add_operand" "rKL")]
UNSPECV_CMPXCHG))
UNSPEC_CMPXCHG))
(clobber (match_scratch:I48MODE 4 "=&r"))]
""
"#"
@ -227,13 +264,44 @@
}
[(set_attr "type" "multi")])
(define_expand "sync_lock_test_and_set<mode>"
[(match_operand:I12MODE 0 "register_operand" "")
(match_operand:I12MODE 1 "memory_operand" "")
(match_operand:I12MODE 2 "register_operand" "")]
""
{
alpha_expand_lock_test_and_set_12 (operands[0], operands[1], operands[2]);
DONE;
})
(define_insn_and_split "sync_lock_test_and_set<mode>_1"
[(set (match_operand:DI 0 "register_operand" "=&r")
(zero_extend:DI
(mem:I12MODE (match_operand:DI 1 "register_operand" "r"))))
(set (mem:I12MODE (match_dup 1))
(unspec:I12MODE
[(match_operand:DI 2 "reg_or_8bit_operand" "rI")
(match_operand:DI 3 "register_operand" "r")]
UNSPEC_XCHG))
(clobber (match_scratch:DI 4 "=&r"))]
""
"#"
"reload_completed"
[(const_int 0)]
{
alpha_split_lock_test_and_set_12 (<MODE>mode, operands[0], operands[1],
operands[2], operands[3], operands[4]);
DONE;
}
[(set_attr "type" "multi")])
(define_insn_and_split "sync_lock_test_and_set<mode>"
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
(match_operand:I48MODE 1 "memory_operand" "+m"))
(set (match_dup 1)
(unspec_volatile:I48MODE
(unspec:I48MODE
[(match_operand:I48MODE 2 "add_operand" "rKL")]
UNSPECV_XCHG))
UNSPEC_XCHG))
(clobber (match_scratch:I48MODE 3 "=&r"))]
""
"#"

View File

@ -1,3 +1,8 @@
2005-07-09 Richard Henderson <rth@redhat.com>
* lib/target-supports.exp (check_effective_target_sync_char_short):
Add alpha.
2005-07-09 Thomas Koenig <Thomas.Koenig@online.de>
PR libfortran/22217

View File

@ -1122,6 +1122,7 @@ proc check_effective_target_sync_char_short { } {
if { [istarget ia64-*-*]
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
|| [istarget alpha*-*-*]
|| [istarget powerpc*-*-*] } {
set et_sync_char_short_saved 1
}