s390.c (s390_expand_atomic): New function.

2005-12-07  Adrian Straetling  <straetling@de.ibm.com>

	* config/s390/s390.c (s390_expand_atomic): New function.
	Adjust comment of helper functions.
	* config/s390/s390-protos.h (s390_expand_atomic): Declare.
	* config/s390/s390.md ("ATOMIC"): New code macro.
	("atomic"): Corresponding new code attribute.
	("sync_lock_test_and_set[hq]i", 
	"sync_{new_,old_,}{and,ior,xor,add,sub,nand}[hq]i"): New pattern.

From-SVN: r108180
This commit is contained in:
Adrian Straetling 2005-12-07 20:01:30 +00:00 committed by Ulrich Weigand
parent 3093f076e1
commit 45d18331f6
4 changed files with 153 additions and 6 deletions

View File

@ -1,3 +1,13 @@
2005-12-07 Adrian Straetling <straetling@de.ibm.com>
* config/s390/s390.c (s390_expand_atomic): New function.
Adjust comment of helper functions.
* config/s390/s390-protos.h (s390_expand_atomic): Declare.
* config/s390/s390.md ("ATOMIC"): New code macro.
("atomic"): Corresponding new code attribute.
("sync_lock_test_and_set[hq]i",
"sync_{new_,old_,}{and,ior,xor,add,sub,nand}[hq]i"): New pattern.
2005-12-07 Adrian Straetling <straetling@de.ibm.com>
* config/s390/s390.c (s390_expand_mask_and_shift,

View File

@ -76,6 +76,8 @@ extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
extern bool s390_expand_insv (rtx, rtx, rtx, rtx);
extern void s390_expand_cs_hqi (enum machine_mode, rtx, rtx, rtx, rtx);
extern void s390_expand_atomic (enum machine_mode, enum rtx_code,
rtx, rtx, rtx, bool);
extern rtx s390_return_addr_rtx (int, rtx);
extern rtx s390_back_chain_rtx (void);
extern rtx s390_emit_call (rtx, rtx, rtx, rtx);

View File

@ -3972,8 +3972,8 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
return false;
}
/* A subroutine of s390_expand_cs_hqi which returns a register which holds VAL
of mode MODE shifted by COUNT bits. */
/* A subroutine of s390_expand_cs_hqi and s390_expand_atomic which returns a
register that holds VAL of mode MODE shifted by COUNT bits. */
static inline rtx
s390_expand_mask_and_shift (rtx val, enum machine_mode mode, rtx count)
@ -3996,10 +3996,10 @@ struct alignment_context
bool aligned; /* True if memory is aliged, false else. */
};
/* A subroutine of s390_expand_cs_hqi to initialize the structure AC for
transparent simplifying, if the memory alignment is known to be at least
32bit. MEM is the memory location for the actual operation and MODE its
mode. */
/* A subroutine of s390_expand_cs_hqi and s390_expand_atomic to initialize
structure AC for transparent simplifying, if the memory alignment is known
to be at least 32bit. MEM is the memory location for the actual operation
and MODE its mode. */
static void
init_alignment_context (struct alignment_context *ac, rtx mem,
@ -4122,6 +4122,97 @@ s390_expand_cs_hqi (enum machine_mode mode, rtx target, rtx mem, rtx cmp, rtx ne
NULL_RTX, 1, OPTAB_DIRECT), 1);
}
/* Expand an atomic operation CODE of mode MODE. MEM is the memory location
and VAL the value to play with. If AFTER is true then store the the value
MEM holds after the operation, if AFTER is false then store the value MEM
holds before the operation. If TARGET is zero then discard that value, else
store it to TARGET. */
void
s390_expand_atomic (enum machine_mode mode, enum rtx_code code,
rtx target, rtx mem, rtx val, bool after)
{
struct alignment_context ac;
rtx cmp;
rtx new = gen_reg_rtx (SImode);
rtx orig = gen_reg_rtx (SImode);
rtx csloop = gen_label_rtx ();
gcc_assert (!target || register_operand (target, VOIDmode));
gcc_assert (MEM_P (mem));
init_alignment_context (&ac, mem, mode);
/* Shift val to the correct bit positions.
Preserve "icm", but prevent "ex icm". */
if (!(ac.aligned && code == SET && MEM_P (val)))
val = s390_expand_mask_and_shift (val, mode, ac.shift);
/* Further preparation insns. */
if (code == PLUS || code == MINUS)
emit_move_insn (orig, val);
else if (code == MULT || code == AND) /* val = "11..1<val>11..1" */
val = expand_simple_binop (SImode, XOR, val, ac.modemaski,
NULL_RTX, 1, OPTAB_DIRECT);
/* Load full word. Subsequent loads are performed by CS. */
cmp = force_reg (SImode, ac.memsi);
/* Start CS loop. */
emit_label (csloop);
emit_move_insn (new, cmp);
/* Patch new with val at correct position. */
switch (code)
{
case PLUS:
case MINUS:
val = expand_simple_binop (SImode, code, new, orig,
NULL_RTX, 1, OPTAB_DIRECT);
val = expand_simple_binop (SImode, AND, val, ac.modemask,
NULL_RTX, 1, OPTAB_DIRECT);
/* FALLTHRU */
case SET:
if (ac.aligned && MEM_P (val))
store_bit_field (new, GET_MODE_BITSIZE (mode), 0, SImode, val);
else
{
new = expand_simple_binop (SImode, AND, new, ac.modemaski,
NULL_RTX, 1, OPTAB_DIRECT);
new = expand_simple_binop (SImode, IOR, new, val,
NULL_RTX, 1, OPTAB_DIRECT);
}
break;
case AND:
case IOR:
case XOR:
new = expand_simple_binop (SImode, code, new, val,
NULL_RTX, 1, OPTAB_DIRECT);
break;
case MULT: /* NAND */
new = expand_simple_binop (SImode, XOR, new, ac.modemask,
NULL_RTX, 1, OPTAB_DIRECT);
new = expand_simple_binop (SImode, AND, new, val,
NULL_RTX, 1, OPTAB_DIRECT);
break;
default:
gcc_unreachable ();
}
/* Emit compare_and_swap pattern. */
emit_insn (gen_sync_compare_and_swap_ccsi (cmp, ac.memsi, cmp, new));
/* Loop until swapped (unlikely?). */
s390_emit_jump (csloop, gen_rtx_fmt_ee (NE, CCZ1mode,
gen_rtx_REG (CCZ1mode, CC_REGNUM),
const0_rtx));
/* Return the correct part of the bitfield. */
if (target)
convert_move (target, expand_simple_binop (SImode, LSHIFTRT,
after ? new : cmp, ac.shift,
NULL_RTX, 1, OPTAB_DIRECT), 1);
}
/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */

View File

@ -315,6 +315,11 @@
;; the same template.
(define_code_macro SHIFT [ashift lshiftrt])
;; These macros allow to combine most atomic operations.
(define_code_macro ATOMIC [and ior xor plus minus mult])
(define_code_attr atomic [(and "and") (ior "ior") (xor "xor")
(plus "add") (minus "sub") (mult "nand")])
;; In FPR templates, a string like "lt<de>br" will expand to "ltdbr" in DFmode
;; and "ltebr" in SFmode.
@ -7340,6 +7345,45 @@
(set_attr "type" "sem")])
;
; Other atomic instruction patterns.
;
(define_expand "sync_lock_test_and_set<mode>"
[(match_operand:HQI 0 "register_operand")
(match_operand:HQI 1 "memory_operand")
(match_operand:HQI 2 "general_operand")]
""
"s390_expand_atomic (<MODE>mode, SET, operands[0], operands[1],
operands[2], false); DONE;")
(define_expand "sync_<atomic><mode>"
[(set (match_operand:HQI 0 "memory_operand")
(ATOMIC:HQI (match_dup 0)
(match_operand:HQI 1 "general_operand")))]
""
"s390_expand_atomic (<MODE>mode, <CODE>, NULL_RTX, operands[0],
operands[1], false); DONE;")
(define_expand "sync_old_<atomic><mode>"
[(set (match_operand:HQI 0 "register_operand")
(match_operand:HQI 1 "memory_operand"))
(set (match_dup 1)
(ATOMIC:HQI (match_dup 1)
(match_operand:HQI 2 "general_operand")))]
""
"s390_expand_atomic (<MODE>mode, <CODE>, operands[0], operands[1],
operands[2], false); DONE;")
(define_expand "sync_new_<atomic><mode>"
[(set (match_operand:HQI 0 "register_operand")
(ATOMIC:HQI (match_operand:HQI 1 "memory_operand")
(match_operand:HQI 2 "general_operand")))
(set (match_dup 1) (ATOMIC:HQI (match_dup 1) (match_dup 2)))]
""
"s390_expand_atomic (<MODE>mode, <CODE>, operands[0], operands[1],
operands[2], true); DONE;")
;;
;;- Miscellaneous instructions.
;;