summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.md11
-rw-r--r--gcc/config/i386/sync.md118
-rw-r--r--gcc/config/s390/predicates.md5
-rw-r--r--gcc/config/s390/s390.c37
-rw-r--r--gcc/config/s390/s390.h2
-rw-r--r--gcc/config/s390/s390.md43
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;
})