Commit 915167f5 by Geoffrey Keating Committed by Geoffrey Keating

Index: ChangeLog

2005-04-21  Geoffrey Keating  <geoffk@apple.com>

	* config/rs6000/rs6000-protos.h (rs6000_emit_sync): New.
	* config/rs6000/rs6000.c (rs6000_emit_vector_compare): Use
	gen_rtx_* not gen_rtx_fmt_*.
	(rs6000_emit_vector_select): Likewise.
	(rs6000_emit_sync): New.
	* config/rs6000/rs6000.md (GPR, INT, INT1): New mode macros.
	(larx, stcx, cmp): New mode substitutions.
	(UNSPEC_SYNC, UNSPEC_SYNC_OP, UNSPEC_SYNC_SWAP, UNSPEC_LWSYNC,
	UNSPEC_ISYNC): New constants.
	(rlwinm): Give name.
	(memory_barrier, isync, lwsync): New insns.
	(sync_compare_and_swap<mode>, sync_lock_test_and_set<mode>): New insn.
	(sync_lock_release<mode>): New expander.
	(sync_add<mode>, sync_sub<mode>, sync_ior<mode>, sync_and<mode>,
	sync_xor<mode>, sync_nand<mode>, sync_old_add<mode>,
	sync_old_sub<mode>, sync_old_ior<mode>, sync_old_and<mode>,
	sync_old_xor<mode>, sync_old_nand<mode>, sync_new_add<mode>,
	sync_new_sub<mode>, sync_new_ior<mode>, sync_new_and<mode>,
	sync_new_xor<mode>, sync_new_nand<mode>): New expanders.
	(sync_add<mode>_internal, sync_addshort_internal,
	sync_sub<mode>_internal, sync_andsi_internal, sync_anddi_internal,
	sync_boolsi_internal, sync_booldi_internal, sync_boolc<mode>_internal,
	sync_boolc<mode>_internal2, sync_boolcc<mode>_internal): New insns.

	* doc/md.texi (Standard Names): sync_compare_and_swap's operand 0
	is the memory before, not after, the operation.  Clarify
	barrier requirements.

Index: testsuite/ChangeLog
2005-04-21  Geoffrey Keating  <geoffk@apple.com>

	* lib/target-supports.exp (check_effective_target_sync_int_long):
	Add powerpc*.

From-SVN: r98527
parent 8fd5bcbe
2005-04-21 Geoffrey Keating <geoffk@apple.com>
* config/rs6000/rs6000-protos.h (rs6000_emit_sync): New.
* config/rs6000/rs6000.c (rs6000_emit_vector_compare): Use
gen_rtx_* not gen_rtx_fmt_*.
(rs6000_emit_vector_select): Likewise.
(rs6000_emit_sync): New.
* config/rs6000/rs6000.md (GPR, INT, INT1): New mode macros.
(larx, stcx, cmp): New mode substitutions.
(UNSPEC_SYNC, UNSPEC_SYNC_OP, UNSPEC_SYNC_SWAP, UNSPEC_LWSYNC,
UNSPEC_ISYNC): New constants.
(rlwinm): Give name.
(memory_barrier, isync, lwsync): New insns.
(sync_compare_and_swap<mode>, sync_lock_test_and_set<mode>): New insn.
(sync_lock_release<mode>): New expander.
(sync_add<mode>, sync_sub<mode>, sync_ior<mode>, sync_and<mode>,
sync_xor<mode>, sync_nand<mode>, sync_old_add<mode>,
sync_old_sub<mode>, sync_old_ior<mode>, sync_old_and<mode>,
sync_old_xor<mode>, sync_old_nand<mode>, sync_new_add<mode>,
sync_new_sub<mode>, sync_new_ior<mode>, sync_new_and<mode>,
sync_new_xor<mode>, sync_new_nand<mode>): New expanders.
(sync_add<mode>_internal, sync_addshort_internal,
sync_sub<mode>_internal, sync_andsi_internal, sync_anddi_internal,
sync_boolsi_internal, sync_booldi_internal, sync_boolc<mode>_internal,
sync_boolc<mode>_internal2, sync_boolcc<mode>_internal): New insns.
* doc/md.texi (Standard Names): sync_compare_and_swap's operand 0
is the memory before, not after, the operation. Clarify
barrier requirements.
2005-04-21 Nathan Sidwell <nathan@codesourcery.com> 2005-04-21 Nathan Sidwell <nathan@codesourcery.com>
* cfghooks.h (struct cfg_hooks): Reword comments to avoid 'abort'. * cfghooks.h (struct cfg_hooks): Reword comments to avoid 'abort'.
......
...@@ -80,6 +80,8 @@ extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int); ...@@ -80,6 +80,8 @@ extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx); extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx); extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx); extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
extern void rs6000_emit_sync (enum rtx_code, enum machine_mode,
rtx, rtx, rtx, rtx, bool);
extern void output_toc (FILE *, rtx, int, enum machine_mode); extern void output_toc (FILE *, rtx, int, enum machine_mode);
extern void rs6000_initialize_trampoline (rtx, rtx, rtx); extern void rs6000_initialize_trampoline (rtx, rtx, rtx);
extern rtx rs6000_longcall_ref (rtx); extern rtx rs6000_longcall_ref (rtx);
......
...@@ -10620,12 +10620,10 @@ rs6000_emit_vector_compare (enum rtx_code rcode, ...@@ -10620,12 +10620,10 @@ rs6000_emit_vector_compare (enum rtx_code rcode,
} }
} }
emit_insn (gen_rtx_fmt_ee (SET, emit_insn (gen_rtx_SET (VOIDmode, mask,
VOIDmode, gen_rtx_UNSPEC (dest_mode,
mask, gen_rtvec (2, op0, op1),
gen_rtx_fmt_Ei (UNSPEC, dest_mode, vec_cmp_insn)));
gen_rtvec (2, op0, op1),
vec_cmp_insn)));
if (dmode != dest_mode) if (dmode != dest_mode)
{ {
rtx temp = gen_reg_rtx (dest_mode); rtx temp = gen_reg_rtx (dest_mode);
...@@ -10676,10 +10674,10 @@ rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask) ...@@ -10676,10 +10674,10 @@ rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
/* For each vector element, select op1 when mask is 1 otherwise /* For each vector element, select op1 when mask is 1 otherwise
select op2. */ select op2. */
t = gen_rtx_fmt_ee (SET, VOIDmode, temp, t = gen_rtx_SET (VOIDmode, temp,
gen_rtx_fmt_Ei (UNSPEC, dest_mode, gen_rtx_UNSPEC (dest_mode,
gen_rtvec (3, op2, op1, mask), gen_rtvec (3, op2, op1, mask),
vsel_insn_index)); vsel_insn_index));
emit_insn (t); emit_insn (t);
emit_move_insn (dest, temp); emit_move_insn (dest, temp);
return; return;
...@@ -10960,6 +10958,183 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1) ...@@ -10960,6 +10958,183 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
emit_move_insn (dest, target); emit_move_insn (dest, target);
} }
/* Emit instructions to perform a load-reserved/store-conditional operation.
The operation performed is an atomic
(set M (CODE:MODE M OP))
If not NULL, BEFORE is atomically set to M before the operation, and
AFTER is set to M after the operation (that is, (CODE:MODE M OP)).
If SYNC_P then a memory barrier is emitted before the operation.
Either OP or M may be wrapped in a NOT operation. */
void
rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
rtx m, rtx op, rtx before_param, rtx after_param,
bool sync_p)
{
enum machine_mode used_mode;
rtx the_op, set_before, set_after, set_atomic, cc_scratch, before, after;
rtx used_m;
rtvec vec;
HOST_WIDE_INT imask = GET_MODE_MASK (mode);
rtx shift = NULL_RTX;
if (sync_p)
emit_insn (gen_memory_barrier ());
if (GET_CODE (m) == NOT)
used_m = XEXP (m, 0);
else
used_m = m;
/* If this is smaller than SImode, we'll have to use SImode with
adjustments. */
if (mode == QImode || mode == HImode)
{
rtx newop, oldop;
if (MEM_ALIGN (used_m) >= 32)
{
int ishift = 0;
if (BYTES_BIG_ENDIAN)
ishift = GET_MODE_BITSIZE (SImode) - GET_MODE_BITSIZE (mode);
shift = GEN_INT (ishift);
}
else
{
rtx addrSI, aligned_addr;
addrSI = force_reg (SImode, gen_lowpart_common (SImode,
XEXP (used_m, 0)));
shift = gen_reg_rtx (SImode);
emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
GEN_INT (0x18)));
aligned_addr = expand_binop (Pmode, and_optab,
XEXP (used_m, 0),
GEN_INT (-4), NULL_RTX,
1, OPTAB_LIB_WIDEN);
used_m = change_address (used_m, SImode, aligned_addr);
set_mem_align (used_m, 32);
/* It's safe to keep the old alias set of USED_M, because
the operation is atomic and only affects the original
USED_M. */
if (GET_CODE (m) == NOT)
m = gen_rtx_NOT (SImode, used_m);
else
m = used_m;
}
if (GET_CODE (op) == NOT)
{
oldop = lowpart_subreg (SImode, XEXP (op, 0), mode);
oldop = gen_rtx_NOT (SImode, oldop);
}
else
oldop = lowpart_subreg (SImode, op, mode);
switch (code)
{
case IOR:
case XOR:
newop = expand_binop (SImode, and_optab,
oldop, GEN_INT (imask), NULL_RTX,
1, OPTAB_LIB_WIDEN);
emit_insn (gen_ashlsi3 (newop, newop, shift));
break;
case AND:
newop = expand_binop (SImode, ior_optab,
oldop, GEN_INT (~imask), NULL_RTX,
1, OPTAB_LIB_WIDEN);
emit_insn (gen_ashlsi3 (newop, newop, shift));
break;
case PLUS:
{
rtx mask;
newop = expand_binop (SImode, and_optab,
oldop, GEN_INT (imask), NULL_RTX,
1, OPTAB_LIB_WIDEN);
emit_insn (gen_ashlsi3 (newop, newop, shift));
mask = gen_reg_rtx (SImode);
emit_move_insn (mask, GEN_INT (imask));
emit_insn (gen_ashlsi3 (mask, mask, shift));
newop = gen_rtx_AND (SImode, gen_rtx_PLUS (SImode, m, newop),
mask);
newop = gen_rtx_IOR (SImode, newop,
gen_rtx_AND (SImode,
gen_rtx_NOT (SImode, mask),
m));
break;
}
default:
gcc_unreachable ();
}
op = newop;
used_mode = SImode;
before = gen_reg_rtx (used_mode);
after = gen_reg_rtx (used_mode);
}
else
{
used_mode = mode;
before = before_param;
after = after_param;
if (before == NULL_RTX)
before = gen_reg_rtx (used_mode);
if (after == NULL_RTX)
after = gen_reg_rtx (used_mode);
}
if (code == PLUS && used_mode != mode)
the_op = op; /* Computed above. */
else if (GET_CODE (op) == NOT && GET_CODE (m) != NOT)
the_op = gen_rtx_fmt_ee (code, used_mode, op, m);
else
the_op = gen_rtx_fmt_ee (code, used_mode, m, op);
set_after = gen_rtx_SET (VOIDmode, after, the_op);
set_before = gen_rtx_SET (VOIDmode, before, used_m);
set_atomic = gen_rtx_SET (VOIDmode, used_m,
gen_rtx_UNSPEC (used_mode, gen_rtvec (1, the_op),
UNSPEC_SYNC_OP));
cc_scratch = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (CCmode));
if (code == PLUS && used_mode != mode)
vec = gen_rtvec (5, set_after, set_before, set_atomic, cc_scratch,
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
else
vec = gen_rtvec (4, set_after, set_before, set_atomic, cc_scratch);
emit_insn (gen_rtx_PARALLEL (VOIDmode, vec));
/* Shift and mask the return values properly. */
if (used_mode != mode && before_param)
{
emit_insn (gen_lshrsi3 (before, before, shift));
convert_move (before_param, before, 1);
}
if (used_mode != mode && after_param)
{
emit_insn (gen_lshrsi3 (after, after, shift));
convert_move (after_param, after, 1);
}
/* The previous sequence will end with a branch that's dependent on
the conditional store, so placing an isync will ensure that no
other instructions (especially, no load or store instructions)
can start before the atomic operation completes. */
if (sync_p)
emit_insn (gen_isync ());
}
/* Emit instructions to move SRC to DST. Called by splitters for /* Emit instructions to move SRC to DST. Called by splitters for
multi-register moves. It will emit at most one instruction for multi-register moves. It will emit at most one instruction for
each register that is accessed; that is, it won't emit li/lis pairs each register that is accessed; that is, it won't emit li/lis pairs
......
...@@ -3952,14 +3952,16 @@ operation. Operand 1 is the memory on which the atomic operation is ...@@ -3952,14 +3952,16 @@ operation. Operand 1 is the memory on which the atomic operation is
performed. Operand 2 is the ``old'' value to be compared against the performed. Operand 2 is the ``old'' value to be compared against the
current contents of the memory location. Operand 3 is the ``new'' value current contents of the memory location. Operand 3 is the ``new'' value
to store in the memory if the compare succeeds. Operand 0 is the result to store in the memory if the compare succeeds. Operand 0 is the result
of the operation; it should contain the current contents of the memory of the operation; it should contain the contents of the memory
after the operation. If the compare succeeds, this should obviously be before the operation. If the compare succeeds, this should obviously be
a copy of operand 3. a copy of operand 2.
This pattern must show that both operand 0 and operand 1 are modified. This pattern must show that both operand 0 and operand 1 are modified.
This pattern must issue any memory barrier instructions such that the This pattern must issue any memory barrier instructions such that all
pattern as a whole acts as a full barrier. memory operations before the atomic operation occur before the atomic
operation and all memory operations after the atomic operation occur
after the atomic operation.
@cindex @code{sync_compare_and_swap_cc@var{mode}} instruction pattern @cindex @code{sync_compare_and_swap_cc@var{mode}} instruction pattern
@item @samp{sync_compare_and_swap_cc@var{mode}} @item @samp{sync_compare_and_swap_cc@var{mode}}
...@@ -3991,8 +3993,10 @@ Operand 1 is the second operand to the binary operator. ...@@ -3991,8 +3993,10 @@ Operand 1 is the second operand to the binary operator.
The ``nand'' operation is @code{op0 & ~op1}. The ``nand'' operation is @code{op0 & ~op1}.
This pattern must issue any memory barrier instructions such that the This pattern must issue any memory barrier instructions such that all
pattern as a whole acts as a full barrier. memory operations before the atomic operation occur before the atomic
operation and all memory operations after the atomic operation occur
after the atomic operation.
If these patterns are not defined, the operation will be constructed If these patterns are not defined, the operation will be constructed
from a compare-and-swap operation, if defined. from a compare-and-swap operation, if defined.
...@@ -4013,8 +4017,10 @@ Operand 0 is the result value, operand 1 is the memory on which the ...@@ -4013,8 +4017,10 @@ Operand 0 is the result value, operand 1 is the memory on which the
atomic operation is performed, and operand 2 is the second operand atomic operation is performed, and operand 2 is the second operand
to the binary operator. to the binary operator.
This pattern must issue any memory barrier instructions such that the This pattern must issue any memory barrier instructions such that all
pattern as a whole acts as a full barrier. memory operations before the atomic operation occur before the atomic
operation and all memory operations after the atomic operation occur
after the atomic operation.
If these patterns are not defined, the operation will be constructed If these patterns are not defined, the operation will be constructed
from a compare-and-swap operation, if defined. from a compare-and-swap operation, if defined.
...@@ -4052,7 +4058,8 @@ an atomic test-and-set bit operation. The result operand should contain ...@@ -4052,7 +4058,8 @@ an atomic test-and-set bit operation. The result operand should contain
The true contents of the memory operand are implementation defined. The true contents of the memory operand are implementation defined.
This pattern must issue any memory barrier instructions such that the This pattern must issue any memory barrier instructions such that the
pattern as a whole acts as an acquire barrier. pattern as a whole acts as an acquire barrier, that is all memory
operations after the pattern do not occur until the lock is acquired.
If this pattern is not defined, the operation will be constructed from If this pattern is not defined, the operation will be constructed from
a compare-and-swap operation, if defined. a compare-and-swap operation, if defined.
...@@ -4065,7 +4072,8 @@ This pattern, if defined, releases a lock set by ...@@ -4065,7 +4072,8 @@ This pattern, if defined, releases a lock set by
that contains the lock. that contains the lock.
This pattern must issue any memory barrier instructions such that the This pattern must issue any memory barrier instructions such that the
pattern as a whole acts as a release barrier. pattern as a whole acts as a release barrier, that is the lock is
released only after all previous memory operations have completed.
If this pattern is not defined, then a @code{memory_barrier} pattern If this pattern is not defined, then a @code{memory_barrier} pattern
will be emitted, followed by a store of zero to the memory operand. will be emitted, followed by a store of zero to the memory operand.
......
2005-04-21 Geoffrey Keating <geoffk@apple.com>
* lib/target-supports.exp (check_effective_target_sync_int_long):
Add powerpc*.
2005-04-21 Richard Sandiford <rsandifo@redhat.com> 2005-04-21 Richard Sandiford <rsandifo@redhat.com>
* gcc.target/mips/branch-1.c: New test. * gcc.target/mips/branch-1.c: New test.
......
...@@ -883,10 +883,13 @@ proc check_effective_target_sync_int_long { } { ...@@ -883,10 +883,13 @@ proc check_effective_target_sync_int_long { } {
verbose "check_effective_target_sync_int_long: using cached result" 2 verbose "check_effective_target_sync_int_long: using cached result" 2
} else { } else {
set et_sync_int_long_saved 0 set et_sync_int_long_saved 0
# This is intentionally powerpc but not rs6000, rs6000 doesn't have the
# load-reserved/store-conditional instructions.
if { [istarget ia64-*-*] if { [istarget ia64-*-*]
|| [istarget i?86-*-*] || [istarget i?86-*-*]
|| [istarget x86_64-*-*] || [istarget x86_64-*-*]
|| [istarget alpha*-*-*] } { || [istarget alpha*-*-*]
|| [istarget powerpc*-*-*] } {
set et_sync_int_long_saved 1 set et_sync_int_long_saved 1
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment