diff options
author | bonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-09 10:57:03 +0000 |
---|---|---|
committer | bonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-09 10:57:03 +0000 |
commit | 8e58adedb84424f61133e374c843541d797b13d0 (patch) | |
tree | ece9481c78c8bf125765823a7704da2edc3e28dd /gcc | |
parent | 7df608798f267536b6399436eaaedfbfdf9c299f (diff) | |
download | gcc-8e58adedb84424f61133e374c843541d797b13d0.tar.gz |
2009-04-09 Paolo Bonzini <bonzini@gnu.org>
* config/i386/i386.md (cmpcc): New.
* config/i386/sync.md (sync_compare_and_swap*): Set FLAGS_REG.
(sync_compare_and_swap_cc*): Delete.
* config/s390/s390.c (s390_compare_emitted): Remove.
(s390_emit_compare): Handle MODE_CC s390_compare_op0 like
s390_compare_emitted used to be handled. Assert that modes match.
(s390_emit_compare_and_swap): Use s390_emit_compare, do not
refer to sync_compare_and_swap_ccsi.
* config/s390/s390.h (s390_compare_emitted): Remove.
* config/s390/s390.md (seq): Look for MODE_CC s390_compare_op0
instead of s390_compare_emitted.
(stack_protect_test, sync_compare_and_swap_cc): Set s390_compare_op0
instead of s390_compare_emitted.
* config/s390/s390.md (cmpcc): New.
(sync_compare_and_swapqi, sync_compare_and_swaphi): Clobber
CC_REGNUM, do not pretend it's set.
(sync_compare_and_swap_cc*): Delete.
* config/s390/predicates.md (cc_reg_operand): New.
* expr.c (sync_compare_and_swap_cc): Delete.
* optabs.h (sync_compare_and_swap_cc): Delete.
* optabs.c (prepare_cmp_insn): Ignore which specific CCmode
is being used with can_compare_p.
(emit_cmp_and_jump_insn_1): Likewise when looking in the optab.
(find_cc_set): New.
(expand_bool_compare_and_swap): Do not use sync_compare_and_swap_cc,
look for a MODE_CC set instead. Use emit_store_flag.
(expand_compare_and_swap_loop): Likewise, with some additional
complication to avoid a force_reg when useless. Use
emit_cmp_and_jump_insns.
* genopinit.c (optabs): Delete sync_compare_and_swap_cc.
* doc/md.texi (sync_compare_and_swap_cc): Merge with
sync_compare_and_swap documentation.
java:
2009-04-09 Paolo Bonzini <bonzini@gnu.org>
* builtins.c (compareAndSwapLong_builtin,
compareAndSwapInt_builtin, compareAndSwapObject_builtin,
VMSupportsCS8_builtin): Do not look at sync_compare_and_swap_cc.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145825 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 37 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 11 | ||||
-rw-r--r-- | gcc/config/i386/sync.md | 118 | ||||
-rw-r--r-- | gcc/config/s390/predicates.md | 5 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 37 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 2 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 43 | ||||
-rw-r--r-- | gcc/doc/md.texi | 22 | ||||
-rw-r--r-- | gcc/expr.c | 1 | ||||
-rw-r--r-- | gcc/genopinit.c | 1 | ||||
-rw-r--r-- | gcc/java/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/java/builtins.c | 12 | ||||
-rw-r--r-- | gcc/optabs.c | 170 | ||||
-rw-r--r-- | gcc/optabs.h | 1 |
14 files changed, 190 insertions, 276 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7433c61f6d9..533705578d3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,40 @@ +2009-04-09 Paolo Bonzini <bonzini@gnu.org> + + * config/i386/i386.md (cmpcc): New. + * config/i386/sync.md (sync_compare_and_swap*): Set FLAGS_REG. + (sync_compare_and_swap_cc*): Delete. + + * config/s390/s390.c (s390_compare_emitted): Remove. + (s390_emit_compare): Handle MODE_CC s390_compare_op0 like + s390_compare_emitted used to be handled. Assert that modes match. + (s390_emit_compare_and_swap): Use s390_emit_compare, do not + refer to sync_compare_and_swap_ccsi. + * config/s390/s390.h (s390_compare_emitted): Remove. + * config/s390/s390.md (seq): Look for MODE_CC s390_compare_op0 + instead of s390_compare_emitted. + (stack_protect_test, sync_compare_and_swap_cc): Set s390_compare_op0 + instead of s390_compare_emitted. + * config/s390/s390.md (cmpcc): New. + (sync_compare_and_swapqi, sync_compare_and_swaphi): Clobber + CC_REGNUM, do not pretend it's set. + (sync_compare_and_swap_cc*): Delete. + * config/s390/predicates.md (cc_reg_operand): New. + + * expr.c (sync_compare_and_swap_cc): Delete. + * optabs.h (sync_compare_and_swap_cc): Delete. + * optabs.c (prepare_cmp_insn): Ignore which specific CCmode + is being used with can_compare_p. + (emit_cmp_and_jump_insn_1): Likewise when looking in the optab. + (find_cc_set): New. + (expand_bool_compare_and_swap): Do not use sync_compare_and_swap_cc, + look for a MODE_CC set instead. Use emit_store_flag. + (expand_compare_and_swap_loop): Likewise, with some additional + complication to avoid a force_reg when useless. Use + emit_cmp_and_jump_insns. + * genopinit.c (optabs): Delete sync_compare_and_swap_cc. + * doc/md.texi (sync_compare_and_swap_cc): Merge with + sync_compare_and_swap documentation. + 2009-04-09 Jan Hubicka <jh@suse.cz> * except.c (find_prev_try): Break out from .... diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b388cd16bfb..a72c1b7232e 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1083,6 +1083,17 @@ DONE; }) +(define_expand "cmpcc" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand 0 "flags_reg_operand" "") + (match_operand 1 "general_operand" "")))] + "" +{ + ix86_compare_op0 = operands[0]; + ix86_compare_op1 = operands[1]; + DONE; +}) + ;; FP compares, step 1: ;; Set the FP condition codes. ;; diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md index 7f92c14b3c5..7167a71932a 100644 --- a/gcc/config/i386/sync.md +++ b/gcc/config/i386/sync.md @@ -70,7 +70,11 @@ (match_operand:CASMODE 2 "register_operand" "") (match_operand:CASMODE 3 "register_operand" "")] UNSPECV_CMPXCHG)) - (clobber (reg:CC FLAGS_REG))])] + (set (reg:CCZ FLAGS_REG) + (compare:CCZ + (unspec_volatile:CASMODE + [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG) + (match_dup 2)))])] "TARGET_CMPXCHG" { if ((<MODE>mode == DImode && !TARGET_64BIT) || <MODE>mode == TImode) @@ -109,7 +113,11 @@ (match_operand:IMODE 2 "register_operand" "a") (match_operand:IMODE 3 "register_operand" "<modeconstraint>")] UNSPECV_CMPXCHG)) - (clobber (reg:CC FLAGS_REG))] + (set (reg:CCZ FLAGS_REG) + (compare:CCZ + (unspec_volatile:IMODE + [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG) + (match_dup 2)))] "TARGET_CMPXCHG" "lock{%;| }cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}") @@ -123,7 +131,12 @@ (match_operand:<DCASHMODE> 3 "register_operand" "b") (match_operand:<DCASHMODE> 4 "register_operand" "c")] UNSPECV_CMPXCHG)) - (clobber (reg:CC FLAGS_REG))] + (set (reg:CCZ FLAGS_REG) + (compare:CCZ + (unspec_volatile:DCASMODE + [(match_dup 1) (match_dup 2) (match_dup 3) (match_dup 4)] + UNSPECV_CMPXCHG) + (match_dup 2)))] "" "lock{%;| }cmpxchg<doublemodesuffix>b\t%1") @@ -146,105 +159,6 @@ (match_operand:SI 3 "register_operand" "SD") (match_operand:SI 4 "register_operand" "c")] UNSPECV_CMPXCHG)) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && TARGET_CMPXCHG8B && flag_pic" - "xchg{l}\t%%ebx, %3\;lock{%;| }cmpxchg8b\t%1\;xchg{l}\t%%ebx, %3") - -(define_expand "sync_compare_and_swap_cc<mode>" - [(parallel - [(set (match_operand:CASMODE 0 "register_operand" "") - (match_operand:CASMODE 1 "memory_operand" "")) - (set (match_dup 1) - (unspec_volatile:CASMODE - [(match_dup 1) - (match_operand:CASMODE 2 "register_operand" "") - (match_operand:CASMODE 3 "register_operand" "")] - UNSPECV_CMPXCHG)) - (set (match_dup 4) - (compare:CCZ - (unspec_volatile:CASMODE - [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG) - (match_dup 2)))])] - "TARGET_CMPXCHG" -{ - operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG); - ix86_compare_op0 = operands[4]; - ix86_compare_op1 = const0_rtx; - if ((<MODE>mode == DImode && !TARGET_64BIT) || <MODE>mode == TImode) - { - enum machine_mode hmode = <MODE>mode == DImode ? SImode : DImode; - rtx low = simplify_gen_subreg (hmode, operands[3], <MODE>mode, 0); - rtx high = simplify_gen_subreg (hmode, operands[3], <MODE>mode, - GET_MODE_SIZE (hmode)); - low = force_reg (hmode, low); - high = force_reg (hmode, high); - if (<MODE>mode == DImode) - { - if (flag_pic && !cmpxchg8b_pic_memory_operand (operands[1], DImode)) - operands[1] = replace_equiv_address (operands[1], - force_reg (Pmode, - XEXP (operands[1], - 0))); - emit_insn (gen_sync_double_compare_and_swap_ccdi - (operands[0], operands[1], operands[2], low, high)); - } - else if (<MODE>mode == TImode) - emit_insn (gen_sync_double_compare_and_swap_ccti - (operands[0], operands[1], operands[2], low, high)); - else - gcc_unreachable (); - DONE; - } -}) - -(define_insn "*sync_compare_and_swap_cc<mode>" - [(set (match_operand:IMODE 0 "register_operand" "=a") - (match_operand:IMODE 1 "memory_operand" "+m")) - (set (match_dup 1) - (unspec_volatile:IMODE - [(match_dup 1) - (match_operand:IMODE 2 "register_operand" "a") - (match_operand:IMODE 3 "register_operand" "<modeconstraint>")] - UNSPECV_CMPXCHG)) - (set (reg:CCZ FLAGS_REG) - (compare:CCZ - (unspec_volatile:IMODE - [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG) - (match_dup 2)))] - "TARGET_CMPXCHG" - "lock{%;| }cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}") - -(define_insn "sync_double_compare_and_swap_cc<mode>" - [(set (match_operand:DCASMODE 0 "register_operand" "=A") - (match_operand:DCASMODE 1 "memory_operand" "+m")) - (set (match_dup 1) - (unspec_volatile:DCASMODE - [(match_dup 1) - (match_operand:DCASMODE 2 "register_operand" "A") - (match_operand:<DCASHMODE> 3 "register_operand" "b") - (match_operand:<DCASHMODE> 4 "register_operand" "c")] - UNSPECV_CMPXCHG)) - (set (reg:CCZ FLAGS_REG) - (compare:CCZ - (unspec_volatile:DCASMODE - [(match_dup 1) (match_dup 2) (match_dup 3) (match_dup 4)] - UNSPECV_CMPXCHG) - (match_dup 2)))] - "" - "lock{%;| }cmpxchg<doublemodesuffix>b\t%1") - -;; See above for the explanation of using the constraint "SD" for -;; operand 3. -(define_insn "*sync_double_compare_and_swap_ccdi_pic" - [(set (match_operand:DI 0 "register_operand" "=A") - (match_operand:DI 1 "cmpxchg8b_pic_memory_operand" "+m")) - (set (match_dup 1) - (unspec_volatile:DI - [(match_dup 1) - (match_operand:DI 2 "register_operand" "A") - (match_operand:SI 3 "register_operand" "SD") - (match_operand:SI 4 "register_operand" "c")] - UNSPECV_CMPXCHG)) (set (reg:CCZ FLAGS_REG) (compare:CCZ (unspec_volatile:DI diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index ca5d17556a5..bb8fdf261d5 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -172,6 +172,11 @@ return (s390_branch_condition_mask (op) >= 0); }) +;; Return true if op is the cc register. +(define_predicate "cc_reg_operand" + (and (match_code "reg") + (match_test "REGNO (op) == CC_REGNUM"))) + (define_predicate "s390_signed_integer_comparison" (match_code "eq, ne, lt, gt, le, ge") { diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index eb08828c29b..1cf9f8eb270 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -224,13 +224,10 @@ struct processor_costs z10_cost = extern int reload_completed; /* Save information from a "cmpxx" operation until the branch or scc is - emitted. */ + emitted. A pair of a MODE_CC register and a const0_rtx if a compare + has been emitted already. */ rtx s390_compare_op0, s390_compare_op1; -/* Save the result of a compare_and_swap until the branch or scc is - emitted. */ -rtx s390_compare_emitted = NULL_RTX; - /* Structure used to hold the components of a S/390 memory address. A legitimate address on S/390 is of the general form @@ -814,23 +811,23 @@ rtx s390_emit_compare (enum rtx_code code, rtx op0, rtx op1) { enum machine_mode mode = s390_select_ccmode (code, op0, op1); - rtx ret = NULL_RTX; + rtx cc; /* Do not output a redundant compare instruction if a compare_and_swap pattern already computed the result and the machine modes are compatible. */ - if (s390_compare_emitted - && (s390_cc_modes_compatible (GET_MODE (s390_compare_emitted), mode) - == GET_MODE (s390_compare_emitted))) - ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx); + if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC) + { + gcc_assert (s390_cc_modes_compatible (GET_MODE (op0), mode) + == GET_MODE (op0)); + cc = op0; + } else { - rtx cc = gen_rtx_REG (mode, CC_REGNUM); - + cc = gen_rtx_REG (mode, CC_REGNUM); emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1))); - ret = gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx); } - s390_compare_emitted = NULL_RTX; - return ret; + + return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx); } /* Emit a SImode compare and swap instruction setting MEM to NEW_RTX if OLD @@ -841,14 +838,8 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1) static rtx s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem, rtx cmp, rtx new_rtx) { - rtx ret; - - emit_insn (gen_sync_compare_and_swap_ccsi (old, mem, cmp, new_rtx)); - ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx); - - s390_compare_emitted = NULL_RTX; - - return ret; + emit_insn (gen_sync_compare_and_swapsi (old, mem, cmp, new_rtx)); + return s390_emit_compare (code, gen_rtx_REG (CCZ1mode, CC_REGNUM), const0_rtx); } /* Emit a jump instruction to TARGET. If COND is NULL_RTX, emit an diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 449c1b64e6e..bfe0268cc77 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -817,7 +817,7 @@ do { \ /* Define the information needed to generate branch and scc insns. This is stored from the compare operation. Note that we can't use "rtx" here since it hasn't been defined! */ -extern struct rtx_def *s390_compare_op0, *s390_compare_op1, *s390_compare_emitted; +extern struct rtx_def *s390_compare_op0, *s390_compare_op1; /* Relative costs of operations. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 7ecc3ccb353..16ed99e08f1 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -515,6 +515,16 @@ DONE; }) +(define_expand "cmpcc" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_operand 0 "cc_reg_operand" "") + (match_operand 1 "general_operand" "")))] + "" +{ + s390_compare_op0 = operands[0]; + s390_compare_op1 = operands[1]; + DONE; +}) ; Test-under-Mask instructions @@ -5122,7 +5132,7 @@ (clobber (reg:CC CC_REGNUM))])] "" { - if (!s390_compare_emitted || GET_MODE (s390_compare_emitted) != CCZ1mode) + if (GET_MODE (s390_compare_op0) != CCZ1mode) FAIL; operands[1] = s390_emit_compare (NE, s390_compare_op0, s390_compare_op1); PUT_MODE (operands[1], SImode); @@ -8242,33 +8252,11 @@ (match_operand:HQI 2 "general_operand" "") (match_operand:HQI 3 "general_operand" "")] UNSPECV_CAS)) - (set (reg:CCZ1 CC_REGNUM) - (compare:CCZ1 (match_dup 1) (match_dup 2)))])] + (clobber (reg:CC CC_REGNUM))])] "" "s390_expand_cs_hqi (<MODE>mode, operands[0], operands[1], operands[2], operands[3]); DONE;") -(define_expand "sync_compare_and_swap_cc<mode>" - [(parallel - [(set (match_operand:TDSI 0 "register_operand" "") - (match_operand:TDSI 1 "memory_operand" "")) - (set (match_dup 1) - (unspec_volatile:TDSI - [(match_dup 1) - (match_operand:TDSI 2 "register_operand" "") - (match_operand:TDSI 3 "register_operand" "")] - UNSPECV_CAS)) - (set (match_dup 4) - (compare:CCZ1 (match_dup 1) (match_dup 2)))])] - "" -{ - /* Emulate compare. */ - operands[4] = gen_rtx_REG (CCZ1mode, CC_REGNUM); - s390_compare_op0 = operands[1]; - s390_compare_op1 = operands[2]; - s390_compare_emitted = operands[4]; -}) - ; cds, cdsg (define_insn "*sync_compare_and_swap<mode>" [(set (match_operand:DP 0 "register_operand" "=r") @@ -8682,17 +8670,14 @@ = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), GEN_INT (TARGET_THREAD_SSP_OFFSET))); #endif - s390_compare_op0 = operands[0]; - s390_compare_op1 = operands[1]; - s390_compare_emitted = gen_rtx_REG (CCZmode, CC_REGNUM); - if (TARGET_64BIT) emit_insn (gen_stack_protect_testdi (operands[0], operands[1])); else emit_insn (gen_stack_protect_testsi (operands[0], operands[1])); + s390_compare_op0 = gen_rtx_REG (CCZmode, CC_REGNUM); + s390_compare_op1 = const0_rtx; emit_jump_insn (gen_beq (operands[2])); - DONE; }) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 25de8b113e8..a78233c8eaa 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -5091,19 +5091,15 @@ 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 -@item @samp{sync_compare_and_swap_cc@var{mode}} - -This pattern is just like @code{sync_compare_and_swap@var{mode}}, except -it should act as if compare part of the compare-and-swap were issued via -@code{cmp@var{m}}. This comparison will only be used with @code{EQ} and -@code{NE} branches and @code{setcc} operations. - -Some targets do expose the success or failure of the compare-and-swap -operation via the status flags. Ideally we wouldn't need a separate -named pattern in order to take advantage of this, but the combine pass -does not handle patterns with multiple sets, which is required by -definition for @code{sync_compare_and_swap@var{mode}}. +For targets where the success or failure of the compare-and-swap +operation is available via the status flags, it is possible +to avoid a separate compare operation and issue the subsequent +setcc or branch immediately after the compare-and-swap. To this +end, GCC will look for a @code{MODE_CC} set in the output of +@code{sync_compare_and_swap@var{mode}}; if the machine description +includes such a set, the target should also define a special @code{cmpcc} +instruction. GCC will then be able to take the destination of the +@code{MODE_CC} set and use it as the first operand of @code{cmpcc}. @cindex @code{sync_add@var{mode}} instruction pattern @cindex @code{sync_sub@var{mode}} instruction pattern diff --git a/gcc/expr.c b/gcc/expr.c index 5836e58c58f..cd530d0a4f4 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -234,7 +234,6 @@ enum insn_code sync_new_and_optab[NUM_MACHINE_MODES]; enum insn_code sync_new_xor_optab[NUM_MACHINE_MODES]; enum insn_code sync_new_nand_optab[NUM_MACHINE_MODES]; enum insn_code sync_compare_and_swap[NUM_MACHINE_MODES]; -enum insn_code sync_compare_and_swap_cc[NUM_MACHINE_MODES]; enum insn_code sync_lock_test_and_set[NUM_MACHINE_MODES]; enum insn_code sync_lock_release[NUM_MACHINE_MODES]; diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 1e778bab3ff..8e13d1ccdf4 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -234,7 +234,6 @@ static const char * const optabs[] = "sync_new_xor_optab[$A] = CODE_FOR_$(sync_new_xor$I$a$)", "sync_new_nand_optab[$A] = CODE_FOR_$(sync_new_nand$I$a$)", "sync_compare_and_swap[$A] = CODE_FOR_$(sync_compare_and_swap$I$a$)", - "sync_compare_and_swap_cc[$A] = CODE_FOR_$(sync_compare_and_swap_cc$I$a$)", "sync_lock_test_and_set[$A] = CODE_FOR_$(sync_lock_test_and_set$I$a$)", "sync_lock_release[$A] = CODE_FOR_$(sync_lock_release$I$a$)", "optab_handler (vec_set_optab, $A)->insn_code = CODE_FOR_$(vec_set$a$)", diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 62c76a77c4f..c4479f28bec 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,9 @@ +2009-04-09 Paolo Bonzini <bonzini@gnu.org> + + * builtins.c (compareAndSwapLong_builtin, + compareAndSwapInt_builtin, compareAndSwapObject_builtin, + VMSupportsCS8_builtin): Do not look at sync_compare_and_swap_cc. + 2009-03-31 Richard Guenther <rguenther@suse.de> * java-gimplify.c (java_gimplify_expr): Do not manually gimplify diff --git a/gcc/java/builtins.c b/gcc/java/builtins.c index c9f9f4a2a79..7ba12d3d431 100644 --- a/gcc/java/builtins.c +++ b/gcc/java/builtins.c @@ -304,8 +304,7 @@ compareAndSwapInt_builtin (tree method_return_type ATTRIBUTE_UNUSED, tree orig_call) { enum machine_mode mode = TYPE_MODE (int_type_node); - if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing - || sync_compare_and_swap[mode] != CODE_FOR_nothing) + if (sync_compare_and_swap[mode] != CODE_FOR_nothing) { tree addr, stmt; UNMARSHAL5 (orig_call); @@ -324,8 +323,7 @@ compareAndSwapLong_builtin (tree method_return_type ATTRIBUTE_UNUSED, tree orig_call) { enum machine_mode mode = TYPE_MODE (long_type_node); - if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing - || sync_compare_and_swap[mode] != CODE_FOR_nothing) + if (sync_compare_and_swap[mode] != CODE_FOR_nothing) { tree addr, stmt; UNMARSHAL5 (orig_call); @@ -343,8 +341,7 @@ compareAndSwapObject_builtin (tree method_return_type ATTRIBUTE_UNUSED, tree orig_call) { enum machine_mode mode = TYPE_MODE (ptr_type_node); - if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing - || sync_compare_and_swap[mode] != CODE_FOR_nothing) + if (sync_compare_and_swap[mode] != CODE_FOR_nothing) { tree addr, stmt; int builtin; @@ -422,8 +419,7 @@ VMSupportsCS8_builtin (tree method_return_type, { enum machine_mode mode = TYPE_MODE (long_type_node); gcc_assert (method_return_type == boolean_type_node); - if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing - || sync_compare_and_swap[mode] != CODE_FOR_nothing) + if (sync_compare_and_swap[mode] != CODE_FOR_nothing) return boolean_true_node; else return boolean_false_node; diff --git a/gcc/optabs.c b/gcc/optabs.c index 7057d9ffa31..058cebe33eb 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4143,11 +4143,15 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, *px = x; *py = y; - if (can_compare_p (*pcomparison, mode, purpose)) + if (GET_MODE_CLASS (mode) == MODE_CC) + { + gcc_assert (can_compare_p (*pcomparison, CCmode, purpose)); + return; + } + else if (can_compare_p (*pcomparison, mode, purpose)) return; /* Handle a lib call just for the mode we are using. */ - libfunc = optab_libfunc (cmp_optab, mode); if (libfunc && !SCALAR_FLOAT_MODE_P (mode)) { @@ -4231,12 +4235,13 @@ emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode, /* Try combined insns first. */ do { + enum machine_mode optab_mode = mclass == MODE_CC ? CCmode : wider_mode; enum insn_code icode; PUT_MODE (test, wider_mode); if (label) { - icode = optab_handler (cbranch_optab, wider_mode)->insn_code; + icode = optab_handler (cbranch_optab, optab_mode)->insn_code; if (icode != CODE_FOR_nothing && insn_data[icode].operand[0].predicate (test, wider_mode)) @@ -4249,7 +4254,7 @@ emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode, } /* Handle some compares against zero. */ - icode = (int) optab_handler (tst_optab, wider_mode)->insn_code; + icode = (int) optab_handler (tst_optab, optab_mode)->insn_code; if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing) { x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp); @@ -4261,7 +4266,7 @@ emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode, /* Handle compares for which there is a directly suitable insn. */ - icode = (int) optab_handler (cmp_optab, wider_mode)->insn_code; + icode = (int) optab_handler (cmp_optab, optab_mode)->insn_code; if (icode != CODE_FOR_nothing) { x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp); @@ -6399,7 +6404,6 @@ init_optabs (void) sync_new_xor_optab[i] = CODE_FOR_nothing; sync_new_nand_optab[i] = CODE_FOR_nothing; sync_compare_and_swap[i] = CODE_FOR_nothing; - sync_compare_and_swap_cc[i] = CODE_FOR_nothing; sync_lock_test_and_set[i] = CODE_FOR_nothing; sync_lock_release[i] = CODE_FOR_nothing; @@ -6970,6 +6974,21 @@ expand_val_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target) return expand_val_compare_and_swap_1 (mem, old_val, new_val, target, icode); } +/* Helper function to find the MODE_CC set in a sync_compare_and_swap + pattern. */ + +static void +find_cc_set (rtx x, const_rtx pat, void *data) +{ + if (REG_P (x) && GET_MODE_CLASS (GET_MODE (x)) == MODE_CC + && GET_CODE (pat) == SET) + { + rtx *p_cc_reg = (rtx *) data; + gcc_assert (!*p_cc_reg); + *p_cc_reg = x; + } +} + /* Expand a compare-and-swap operation and store true into the result if the operation was successful and false otherwise. Return the result. Unlike other routines, TARGET is not optional. */ @@ -6979,84 +6998,46 @@ expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target) { enum machine_mode mode = GET_MODE (mem); enum insn_code icode; - rtx subtarget, label0, label1; + rtx subtarget, seq, cc_reg; /* If the target supports a compare-and-swap pattern that simultaneously sets some flag for success, then use it. Otherwise use the regular compare-and-swap and follow that immediately with a compare insn. */ - icode = sync_compare_and_swap_cc[mode]; - switch (icode) - { - default: - subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val, - NULL_RTX, icode); - if (subtarget != NULL_RTX) - break; - - /* FALLTHRU */ - case CODE_FOR_nothing: - icode = sync_compare_and_swap[mode]; - if (icode == CODE_FOR_nothing) - return NULL_RTX; - - /* Ensure that if old_val == mem, that we're not comparing - against an old value. */ - if (MEM_P (old_val)) - old_val = force_reg (mode, old_val); + icode = sync_compare_and_swap[mode]; + if (icode == CODE_FOR_nothing) + return NULL_RTX; + do + { + start_sequence (); subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val, - NULL_RTX, icode); + NULL_RTX, icode); + cc_reg = NULL_RTX; if (subtarget == NULL_RTX) - return NULL_RTX; - - emit_cmp_insn (subtarget, old_val, EQ, const0_rtx, mode, true); - } - - /* If the target has a sane STORE_FLAG_VALUE, then go ahead and use a - setcc instruction from the beginning. We don't work too hard here, - but it's nice to not be stupid about initial code gen either. */ - if (STORE_FLAG_VALUE == 1) - { - icode = setcc_gen_code[EQ]; - if (icode != CODE_FOR_nothing) { - enum machine_mode cmode = insn_data[icode].operand[0].mode; - rtx insn; - - subtarget = target; - if (!insn_data[icode].operand[0].predicate (target, cmode)) - subtarget = gen_reg_rtx (cmode); - - insn = GEN_FCN (icode) (subtarget); - if (insn) - { - emit_insn (insn); - if (GET_MODE (target) != GET_MODE (subtarget)) - { - convert_move (target, subtarget, 1); - subtarget = target; - } - return subtarget; - } + end_sequence (); + return NULL_RTX; } - } - - /* Without an appropriate setcc instruction, use a set of branches to - get 1 and 0 stored into target. Presumably if the target has a - STORE_FLAG_VALUE that isn't 1, then this will get cleaned up by ifcvt. */ - label0 = gen_label_rtx (); - label1 = gen_label_rtx (); + if (have_insn_for (COMPARE, CCmode)) + note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg); + seq = get_insns (); + end_sequence (); - emit_jump_insn (bcc_gen_fctn[EQ] (label0)); - emit_move_insn (target, const0_rtx); - emit_jump_insn (gen_jump (label1)); - emit_barrier (); - emit_label (label0); - emit_move_insn (target, const1_rtx); - emit_label (label1); + /* We might be comparing against an old value. Try again. :-( */ + if (!cc_reg && MEM_P (old_val)) + { + seq = NULL_RTX; + old_val = force_reg (mode, old_val); + } + } + while (!seq); - return target; + emit_insn (seq); + if (cc_reg) + return emit_store_flag (target, EQ, cc_reg, const0_rtx, VOIDmode, 0, 1); + else + return emit_store_flag (target, EQ, subtarget, old_val, VOIDmode, 1, 1); } /* This is a helper function for the other atomic operations. This function @@ -7073,7 +7054,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq) { enum machine_mode mode = GET_MODE (mem); enum insn_code icode; - rtx label, cmp_reg, subtarget; + rtx label, cmp_reg, subtarget, cc_reg; /* The loop we want to generate looks like @@ -7100,37 +7081,32 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq) /* If the target supports a compare-and-swap pattern that simultaneously sets some flag for success, then use it. Otherwise use the regular compare-and-swap and follow that immediately with a compare insn. */ - icode = sync_compare_and_swap_cc[mode]; - switch (icode) - { - default: - subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg, - cmp_reg, icode); - if (subtarget != NULL_RTX) - { - gcc_assert (subtarget == cmp_reg); - break; - } + icode = sync_compare_and_swap[mode]; + if (icode == CODE_FOR_nothing) + return false; - /* FALLTHRU */ - case CODE_FOR_nothing: - icode = sync_compare_and_swap[mode]; - if (icode == CODE_FOR_nothing) - return false; + subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg, + cmp_reg, icode); + if (subtarget == NULL_RTX) + return false; - subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg, - cmp_reg, icode); - if (subtarget == NULL_RTX) - return false; + cc_reg = NULL_RTX; + if (have_insn_for (COMPARE, CCmode)) + note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg); + if (cc_reg) + { + cmp_reg = cc_reg; + old_reg = const0_rtx; + } + else + { if (subtarget != cmp_reg) emit_move_insn (cmp_reg, subtarget); - - emit_cmp_insn (cmp_reg, old_reg, EQ, const0_rtx, mode, true); } /* ??? Mark this jump predicted not taken? */ - emit_jump_insn (bcc_gen_fctn[NE] (label)); - + emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, const0_rtx, GET_MODE (cmp_reg), 1, + label); return true; } diff --git a/gcc/optabs.h b/gcc/optabs.h index 4d0ce5245ea..a518dc6ab86 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -670,7 +670,6 @@ extern enum insn_code sync_new_nand_optab[NUM_MACHINE_MODES]; /* Atomic compare and swap. */ extern enum insn_code sync_compare_and_swap[NUM_MACHINE_MODES]; -extern enum insn_code sync_compare_and_swap_cc[NUM_MACHINE_MODES]; /* Atomic exchange with acquire semantics. */ extern enum insn_code sync_lock_test_and_set[NUM_MACHINE_MODES]; |