s390.c: (s390_cc_modes_compatible): Move before "s390_emit_compare".

2005-07-13  Adrian Strae�tling  <straetling@de.ibm.com>

	* config/s390/s390.c: (s390_cc_modes_compatible): Move before
	"s390_emit_compare".  Add handling of CCZ1mode.
	(s390_canonicalize_comparison): Simplify cascaded EQ, NE.
	(390_emit_compare): Use "s390_cc_modes_compatible" for mode
	checking.
	(s390_branch_condition_mask): Add CCZ1mode handling.
	* config/s390/s390.md: ("seq", "*seq"): New pattern.
	("sync_compare_and_swap_cc<mode>", "*sync_compare_and_swap_cc<mode>"):
	Use CCZ1mode instead of CCZmode.
	* config/s390/s390-modes.def: Add CCZ1mode.  Comment new mode.

From-SVN: r101990
This commit is contained in:
Adrian Straetling 2005-07-13 19:34:56 +00:00 committed by Ulrich Weigand
parent ccbdc0d46e
commit 6995045258
4 changed files with 110 additions and 40 deletions

View File

@ -1,3 +1,16 @@
2005-07-13 Adrian Strae½tling <straetling@de.ibm.com>
* config/s390/s390.c: (s390_cc_modes_compatible): Move before
"s390_emit_compare". Add handling of CCZ1mode.
(s390_canonicalize_comparison): Simplify cascaded EQ, NE.
(390_emit_compare): Use "s390_cc_modes_compatible" for mode
checking.
(s390_branch_condition_mask): Add CCZ1mode handling.
* config/s390/s390.md: ("seq", "*seq"): New pattern.
("sync_compare_and_swap_cc<mode>", "*sync_compare_and_swap_cc<mode>"):
Use CCZ1mode instead of CCZmode.
* config/s390/s390-modes.def: Add CCZ1mode. Comment new mode.
2006-07-13 Adrian Strae½tling <straetling@de.ibm.com>
* config/s390/s390.md: ("cmpstrsi", "*cmpstr<mode>"): New

View File

@ -35,6 +35,7 @@ Condition Codes
Check for zero
CCZ: EQ NE NE NE
CCZ1: EQ NE (CS)
Unsigned compares
@ -146,10 +147,17 @@ CCL3 mode. Together with the CCU mode this mode is used for jumpless
implementations of several if-constructs - see s390_expand_addcc for more
details.
CCZ1
The compare and swap instructions sets the condition code to 0/1 if the
operands were equal/unequal. The CCZ1 mode ensures the result can be
effectively placed into a register.
*/
CC_MODE (CCZ);
CC_MODE (CCZ1);
CC_MODE (CCA);
CC_MODE (CCAP);
CC_MODE (CCAN);

View File

@ -272,6 +272,41 @@ s390_set_has_landing_pad_p (bool value)
cfun->machine->has_landing_pad_p = value;
}
/* If two condition code modes are compatible, return a condition code
mode which is compatible with both. Otherwise, return
VOIDmode. */
static enum machine_mode
s390_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
{
if (m1 == m2)
return m1;
switch (m1)
{
case CCZmode:
if (m2 == CCUmode || m2 == CCTmode || m2 == CCZ1mode
|| m2 == CCSmode || m2 == CCSRmode || m2 == CCURmode)
return m2;
return VOIDmode;
case CCSmode:
case CCUmode:
case CCTmode:
case CCSRmode:
case CCURmode:
case CCZ1mode:
if (m2 == CCZmode)
return m1;
return VOIDmode;
default:
return VOIDmode;
}
return VOIDmode;
}
/* Return true if SET either doesn't set the CC register, or else
the source and destination have matching CC modes and that
CC mode is at least as constrained as REQ_MODE. */
@ -612,6 +647,23 @@ s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
*code = new_code;
}
}
/* Simplify cascaded EQ, NE with const0_rtx. */
if ((*code == NE || *code == EQ)
&& (GET_CODE (*op0) == EQ || GET_CODE (*op0) == NE)
&& GET_MODE (*op0) == SImode
&& GET_MODE (XEXP (*op0, 0)) == CCZ1mode
&& REG_P (XEXP (*op0, 0))
&& XEXP (*op0, 1) == const0_rtx
&& *op1 == const0_rtx)
{
if ((*code == EQ && GET_CODE (*op0) == NE)
|| (*code == NE && GET_CODE (*op0) == EQ))
*code = EQ;
else
*code = NE;
*op0 = XEXP (*op0, 0);
}
}
/* Emit a compare instruction suitable to implement the comparison
@ -625,8 +677,10 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
rtx ret = NULL_RTX;
/* Do not output a redundant compare instruction if a compare_and_swap
pattern already computed the result and the machine modes match. */
if (s390_compare_emitted && GET_MODE (s390_compare_emitted) == mode)
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);
else
{
@ -673,6 +727,7 @@ s390_branch_condition_mask (rtx code)
switch (GET_MODE (XEXP (code, 0)))
{
case CCZmode:
case CCZ1mode:
switch (GET_CODE (code))
{
case EQ: return CC0;
@ -7910,40 +7965,6 @@ s390_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
return true;
}
/* If two condition code modes are compatible, return a condition code
mode which is compatible with both. Otherwise, return
VOIDmode. */
static enum machine_mode
s390_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
{
if (m1 == m2)
return m1;
switch (m1)
{
case CCZmode:
if (m2 == CCUmode || m2 == CCTmode
|| m2 == CCSmode || m2 == CCSRmode || m2 == CCURmode)
return m2;
return VOIDmode;
case CCSmode:
case CCUmode:
case CCTmode:
case CCSRmode:
case CCURmode:
if (m2 == CCZmode)
return m1;
return VOIDmode;
default:
return VOIDmode;
}
return VOIDmode;
}
/* This function is used by the call expanders of the machine description.
It emits the call insn itself together with the necessary operations
to adjust the target address and returns the emitted insn.

View File

@ -3973,6 +3973,34 @@
"if (!s390_expand_addcc (<CODE>, s390_compare_op0, s390_compare_op1,
operands[0], const0_rtx, const1_rtx)) FAIL; DONE;")
(define_expand "seq"
[(parallel
[(set (match_operand:SI 0 "register_operand" "=d")
(match_dup 1))
(clobber (reg:CC CC_REGNUM))])
(parallel
[(set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))
(clobber (reg:CC CC_REGNUM))])]
""
{
if (!s390_compare_emitted || GET_MODE (s390_compare_emitted) != CCZ1mode)
FAIL;
operands[1] = s390_emit_compare (NE, s390_compare_op0, s390_compare_op1);
PUT_MODE (operands[1], SImode);
})
(define_insn_and_split "*sne"
[(set (match_operand:SI 0 "register_operand" "=d")
(ne:SI (match_operand:CCZ1 1 "register_operand" "0")
(const_int 0)))
(clobber (reg:CC CC_REGNUM))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 28)))
(clobber (reg:CC CC_REGNUM))])])
;;
;;- Multiply instructions.
@ -6797,10 +6825,10 @@
(match_operand:GPR 3 "register_operand" "")]
UNSPECV_CAS))
(set (match_dup 4)
(compare:CCZ (match_dup 1) (match_dup 2)))])]
(compare:CCZ1 (match_dup 1) (match_dup 2)))])]
""
{
operands[4] = gen_rtx_REG (CCZmode, CC_REGNUM);
operands[4] = gen_rtx_REG (CCZ1mode, CC_REGNUM);
s390_compare_op0 = operands[1];
s390_compare_op1 = operands[2];
s390_compare_emitted = operands[4];
@ -6815,8 +6843,8 @@
(match_operand:GPR 2 "register_operand" "0")
(match_operand:GPR 3 "register_operand" "r")]
UNSPECV_CAS))
(set (reg:CCZ CC_REGNUM)
(compare:CCZ (match_dup 1) (match_dup 2)))]
(set (reg:CCZ1 CC_REGNUM)
(compare:CCZ1 (match_dup 1) (match_dup 2)))]
""
"cs<g>\t%0,%3,%S1"
[(set_attr "op_type" "RS<E>")