sync.md (AINT mode_iterator): Move definition.
* config/rs6000/sync.md (AINT mode_iterator): Move definition. (loadsync_<mode>): Change mode. (load_quadpti, store_quadpti): New. (atomic_load<mode>, atomic_store<mode>): Add support for TI mode. * config/rs6000/rs6000.md (unspec enum): Add UNSPEC_LSQ. * gcc.target/powerpc/atomic_load_store-p8.c: New. From-SVN: r209225
This commit is contained in:
parent
795bc4b6fb
commit
98e6ecab8c
|
@ -1,3 +1,11 @@
|
|||
2014-04-08 Pat Haugen <pthaugen@us.ibm.com>
|
||||
|
||||
* config/rs6000/sync.md (AINT mode_iterator): Move definition.
|
||||
(loadsync_<mode>): Change mode.
|
||||
(load_quadpti, store_quadpti): New.
|
||||
(atomic_load<mode>, atomic_store<mode>): Add support for TI mode.
|
||||
* config/rs6000/rs6000.md (unspec enum): Add UNSPEC_LSQ.
|
||||
|
||||
2014-04-08 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
PR target/60763
|
||||
|
|
|
@ -624,14 +624,14 @@
|
|||
(match_test "offsettable_nonstrict_memref_p (op)")))
|
||||
|
||||
;; Return 1 if the operand is suitable for load/store quad memory.
|
||||
;; This predicate only checks for non-atomic loads/stores.
|
||||
;; This predicate only checks for non-atomic loads/stores (not lqarx/stqcx).
|
||||
(define_predicate "quad_memory_operand"
|
||||
(match_code "mem")
|
||||
{
|
||||
rtx addr, op0, op1;
|
||||
int ret;
|
||||
|
||||
if (!TARGET_QUAD_MEMORY)
|
||||
if (!TARGET_QUAD_MEMORY && !TARGET_SYNC_TI)
|
||||
ret = 0;
|
||||
|
||||
else if (!memory_operand (op, mode))
|
||||
|
|
|
@ -125,6 +125,7 @@
|
|||
UNSPEC_P8V_MTVSRD
|
||||
UNSPEC_P8V_XXPERMDI
|
||||
UNSPEC_P8V_RELOAD_FROM_VSX
|
||||
UNSPEC_LSQ
|
||||
])
|
||||
|
||||
;;
|
||||
|
|
|
@ -107,10 +107,17 @@
|
|||
"isync"
|
||||
[(set_attr "type" "isync")])
|
||||
|
||||
;; Types that we should provide atomic instructions for.
|
||||
(define_mode_iterator AINT [QI
|
||||
HI
|
||||
SI
|
||||
(DI "TARGET_POWERPC64")
|
||||
(TI "TARGET_SYNC_TI")])
|
||||
|
||||
;; The control dependency used for load dependency described
|
||||
;; in B.2.3 of the Power ISA 2.06B.
|
||||
(define_insn "loadsync_<mode>"
|
||||
[(unspec_volatile:BLK [(match_operand:INT1 0 "register_operand" "r")]
|
||||
[(unspec_volatile:BLK [(match_operand:AINT 0 "register_operand" "r")]
|
||||
UNSPECV_ISYNC)
|
||||
(clobber (match_scratch:CC 1 "=y"))]
|
||||
""
|
||||
|
@ -118,18 +125,56 @@
|
|||
[(set_attr "type" "isync")
|
||||
(set_attr "length" "12")])
|
||||
|
||||
(define_insn "load_quadpti"
|
||||
[(set (match_operand:PTI 0 "quad_int_reg_operand" "=&r")
|
||||
(unspec:PTI
|
||||
[(match_operand:TI 1 "quad_memory_operand" "wQ")] UNSPEC_LSQ))]
|
||||
"TARGET_SYNC_TI
|
||||
&& !reg_mentioned_p (operands[0], operands[1])"
|
||||
"lq %0,%1"
|
||||
[(set_attr "type" "load")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_expand "atomic_load<mode>"
|
||||
[(set (match_operand:INT1 0 "register_operand" "") ;; output
|
||||
(match_operand:INT1 1 "memory_operand" "")) ;; memory
|
||||
[(set (match_operand:AINT 0 "register_operand" "") ;; output
|
||||
(match_operand:AINT 1 "memory_operand" "")) ;; memory
|
||||
(use (match_operand:SI 2 "const_int_operand" ""))] ;; model
|
||||
""
|
||||
{
|
||||
if (<MODE>mode == TImode && !TARGET_SYNC_TI)
|
||||
FAIL;
|
||||
|
||||
enum memmodel model = (enum memmodel) INTVAL (operands[2]);
|
||||
|
||||
if (model == MEMMODEL_SEQ_CST)
|
||||
emit_insn (gen_hwsync ());
|
||||
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
if (<MODE>mode != TImode)
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
else
|
||||
{
|
||||
rtx op0 = operands[0];
|
||||
rtx op1 = operands[1];
|
||||
rtx pti_reg = gen_reg_rtx (PTImode);
|
||||
|
||||
// Can't have indexed address for 'lq'
|
||||
if (indexed_address (XEXP (op1, 0), TImode))
|
||||
{
|
||||
rtx old_addr = XEXP (op1, 0);
|
||||
rtx new_addr = force_reg (Pmode, old_addr);
|
||||
operands[1] = op1 = replace_equiv_address (op1, new_addr);
|
||||
}
|
||||
|
||||
emit_insn (gen_load_quadpti (pti_reg, op1));
|
||||
|
||||
if (WORDS_BIG_ENDIAN)
|
||||
emit_move_insn (op0, gen_lowpart (TImode, pti_reg));
|
||||
else
|
||||
{
|
||||
emit_move_insn (gen_lowpart (DImode, op0), gen_highpart (DImode, pti_reg));
|
||||
emit_move_insn (gen_highpart (DImode, op0), gen_lowpart (DImode, pti_reg));
|
||||
}
|
||||
}
|
||||
|
||||
switch (model)
|
||||
{
|
||||
|
@ -146,12 +191,24 @@
|
|||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "store_quadpti"
|
||||
[(set (match_operand:PTI 0 "quad_memory_operand" "=wQ")
|
||||
(unspec:PTI
|
||||
[(match_operand:PTI 1 "quad_int_reg_operand" "r")] UNSPEC_LSQ))]
|
||||
"TARGET_SYNC_TI"
|
||||
"stq %1,%0"
|
||||
[(set_attr "type" "store")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_expand "atomic_store<mode>"
|
||||
[(set (match_operand:INT1 0 "memory_operand" "") ;; memory
|
||||
(match_operand:INT1 1 "register_operand" "")) ;; input
|
||||
[(set (match_operand:AINT 0 "memory_operand" "") ;; memory
|
||||
(match_operand:AINT 1 "register_operand" "")) ;; input
|
||||
(use (match_operand:SI 2 "const_int_operand" ""))] ;; model
|
||||
""
|
||||
{
|
||||
if (<MODE>mode == TImode && !TARGET_SYNC_TI)
|
||||
FAIL;
|
||||
|
||||
enum memmodel model = (enum memmodel) INTVAL (operands[2]);
|
||||
switch (model)
|
||||
{
|
||||
|
@ -166,7 +223,33 @@
|
|||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
if (<MODE>mode != TImode)
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
else
|
||||
{
|
||||
rtx op0 = operands[0];
|
||||
rtx op1 = operands[1];
|
||||
rtx pti_reg = gen_reg_rtx (PTImode);
|
||||
|
||||
// Can't have indexed address for 'stq'
|
||||
if (indexed_address (XEXP (op0, 0), TImode))
|
||||
{
|
||||
rtx old_addr = XEXP (op0, 0);
|
||||
rtx new_addr = force_reg (Pmode, old_addr);
|
||||
operands[0] = op0 = replace_equiv_address (op0, new_addr);
|
||||
}
|
||||
|
||||
if (WORDS_BIG_ENDIAN)
|
||||
emit_move_insn (pti_reg, gen_lowpart (PTImode, op1));
|
||||
else
|
||||
{
|
||||
emit_move_insn (gen_lowpart (DImode, pti_reg), gen_highpart (DImode, op1));
|
||||
emit_move_insn (gen_highpart (DImode, pti_reg), gen_lowpart (DImode, op1));
|
||||
}
|
||||
|
||||
emit_insn (gen_store_quadpti (gen_lowpart (PTImode, op0), pti_reg));
|
||||
}
|
||||
|
||||
DONE;
|
||||
})
|
||||
|
||||
|
@ -180,14 +263,6 @@
|
|||
SI
|
||||
(DI "TARGET_POWERPC64")])
|
||||
|
||||
;; Types that we should provide atomic instructions for.
|
||||
|
||||
(define_mode_iterator AINT [QI
|
||||
HI
|
||||
SI
|
||||
(DI "TARGET_POWERPC64")
|
||||
(TI "TARGET_SYNC_TI")])
|
||||
|
||||
(define_insn "load_locked<mode>"
|
||||
[(set (match_operand:ATOMIC 0 "int_reg_operand" "=r")
|
||||
(unspec_volatile:ATOMIC
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2014-04-08 Pat Haugen <pthaugen@us.ibm.com>
|
||||
|
||||
* gcc.target/powerpc/atomic_load_store-p8.c: New.
|
||||
|
||||
2014-04-08 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* lib/gcc-dg.exp (dg-build-dso): Reset dg-do-what-default to
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
|
||||
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
|
||||
/* { dg-require-effective-target powerpc_p8vector_ok } */
|
||||
/* { dg-options "-mcpu=power8 -O2" } */
|
||||
/* { dg-final { scan-assembler-times "lq" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "stq" 1 } } */
|
||||
/* { dg-final { scan-assembler-not "bl __atomic" } } */
|
||||
/* { dg-final { scan-assembler-not "lqarx" } } */
|
||||
/* { dg-final { scan-assembler-not "stqcx" } } */
|
||||
|
||||
__int128
|
||||
atomic_load_128_relaxed (__int128 *ptr)
|
||||
{
|
||||
return __atomic_load_n (ptr, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
void
|
||||
atomic_store_128_relaxed (__int128 *ptr, __int128 val)
|
||||
{
|
||||
__atomic_store_n (ptr, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
Loading…
Reference in New Issue