diff options
Diffstat (limited to 'gcc/config')
-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 |
6 files changed, 61 insertions, 155 deletions
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; }) |