sparc.opt (msubxc): New option.

* config/sparc/sparc.opt (msubxc): New option.
	* doc/invoke.texi (SPARC options): Document it and tidy up.
	* doc/tm.texi.in (Condition Codes): Adjust SPARC example.
	* doc/tm.texi: Regenerate.
	* config/sparc/sparc-modes.def (CC_NOOV): Rename into...
	(CCNZ): ...this.
	(CCX_NOOV): Rename into...
	(CCXNZ): ...this.
	(CCC): New.
	(CCXC): Likewise.
	* config/sparc/predicates.m (fcc_register_operand): Simplify.
	(fcc0_register_operand): Likewise.
	(icc_register_operand): New.
	(icc_or_fcc_register_operand): Simplify.
	(nz_comparison_operator): New.
	(c_comparison_operator): Likewise.
	(noov_compare_operator): Rename into...
	(icc_comparison_operator): ...this.  Use above predicates.
	(noov_compare64_operator): Rename into...
	(v9_comparison_operator): ...this and tidy up.
	(fcc_comparison_operator): New.
	(icc_or_fcc_comparison_operator): Likewise.
	(v9_register_compare_operator): Rename info...
	(v9_register_comparison_operator): ...this.
	* config/sparc/sparc.c (TARGET_FIXED_CONDITION_CODE_REGS): Define.
	(sparc_option_override): Remove redundant VIS masks and add MASK_SUBXC
	for Niagara-7.
	(sparc_fixed_condition_code_regs): New function.
	(select_cc_mode): Remove ATTRIBUTE_UNUSED.  Adjust for CCNZ/CCXNZ
	renaming and add support for CCC/CCXC.
	(output_cbranch): Likewise.
	(sparc_print_operand): Likewise.
	(gen_v9_scc): Remove obsolete assertion.
	(emit_scc_insn): Emit RTL directly for EQ and NE.  Add direct support
	for EQ in DImode if TARGET_SUBXC.  Remove test on TARGET_VIS3 for GEU.
	(output_cbcond): Remove bogus handling of CC modes.
	(sparc_register_move_cost): Return 100 for NO_REGS.
	* config/sparc/sparc.md (W): New mode iterator.
	(length): Adjust for noov_compare64_operator renaming.
	(cmpsi_sne): New instruction.
	(cmpdi_sne): Likewise.
	(seqdi_special): Delete.
	(seqdi_special): Likewise.
	(snesi<P:mode>_special): Likewise.
	(snedi_special): Likewise.
	(snedi_special_vis3): Likewise.
	(snesi patterns): Use W iterator.
	(snedi patterns): Likewise.  Add TARGET_SUBXC patterns.
	(sltu patterns): Likewise.
	(sgeu patterns): Likewise.
	(scc splitter): Do not split GEU in DImode if TARGET_SUBXC.
	(normal_branch): Use icc_comparison_operator predicate.
	(inverted_branch): Likewise.
	(cbcond_sp32): Use comparison_operator predicate.
	(cbcond_sp64): Likewise.
	(normal_int_branch_sp64): Adjust for renaming
	(inverted_int_branch_sp64): Likewise.
	(mov<I:mode>_cc_reg_sp64): Likewise.
	(movsf_cc_reg_sp6): Likewise.
	(movdf_cc_reg_sp64): Likewise.
	(movtf_cc_reg_hq_sp64): Likewise.
	(movtf_cc_reg_sp64): Likewise.
	(mov<I:mode>_cc_v9): Use icc_or_fcc_comparison_operator predicate.
	(movsf_cc_v9): Likewise.
	(movdf_cc_v9): Likewise.
	(movtf_cc_hq_v9): Likewise.
	(movtf_cc_v9): Likewise.
	(adddi3): Call gen_adddi3_sp32.
	(adddi3_insn_sp32): Rename to...
	(adddi3_sp32): ...this.  Accept only register_operand as operand #1
	and use CCCmode for the carry.
	(addx_extend_sp32): Use CCCmode for the carry.
	(addx_extend_sp64): Delete.
	(adddi3_extend_sp32): Use CCCmode for the carry.
	(cmp_plus patterns): Use CCNZ/CCXNZ mode and add C variants.
	(subdi3): Call gen_subdi3_sp32.
	(subdi3_insn_sp32): Rename to...
	(subdi3_sp32): ...this and use CCmode for the carry.
	(subx_extend_sp32): Use CCCmode for the carry.
	(subx_extend_sp64): Delete.
	(subdi3_extend_sp32): Use CCmode for the carry.
	(cmp_minus patterns): Use CCNZ/CCXNZ mode and add C variants.
	(negdi3): Call gen_negdi3_sp32.
	(negdi3_sp32): Use CCCmode for the carry.
	(cmp_neg patterns): Use CCNZ/CCXNZ mode and add C variants.
	(cmp_nz_ashift_1): Use CCNZ mode.
	(cmp_nz_set_ashift_1): Likewise.
	(ctrapsi4): Use comparison_operator predicate.
	(ctrapdi4): Likewise.
	(trapsi_insn): Use icc_comparison_operator predicate.
	(trapdi_insn): Likewise.
	(edge8 patterns): Use CCNZmode.
	(edge16 patterns): Likewise.
	(edge32 patterns): Likewise.

From-SVN: r240971
This commit is contained in:
Eric Botcazou 2016-10-11 08:54:56 +00:00 committed by Eric Botcazou
parent 8d946ecc46
commit ff7e7ee099
24 changed files with 1566 additions and 904 deletions

View File

@ -1,3 +1,100 @@
2016-10-11 Eric Botcazou <ebotcazou@adacore.com>
* config/sparc/sparc.opt (msubxc): New option.
* doc/invoke.texi (SPARC options): Document it and tidy up.
* doc/tm.texi.in (Condition Codes): Adjust SPARC example.
* doc/tm.texi: Regenerate.
* config/sparc/sparc-modes.def (CC_NOOV): Rename into...
(CCNZ): ...this.
(CCX_NOOV): Rename into...
(CCXNZ): ...this.
(CCC): New.
(CCXC): Likewise.
* config/sparc/predicates.m (fcc_register_operand): Simplify.
(fcc0_register_operand): Likewise.
(icc_register_operand): New.
(icc_or_fcc_register_operand): Simplify.
(nz_comparison_operator): New.
(c_comparison_operator): Likewise.
(noov_compare_operator): Rename into...
(icc_comparison_operator): ...this. Use above predicates.
(noov_compare64_operator): Rename into...
(v9_comparison_operator): ...this and tidy up.
(fcc_comparison_operator): New.
(icc_or_fcc_comparison_operator): Likewise.
(v9_register_compare_operator): Rename info...
(v9_register_comparison_operator): ...this.
* config/sparc/sparc.c (TARGET_FIXED_CONDITION_CODE_REGS): Define.
(sparc_option_override): Remove redundant VIS masks and add MASK_SUBXC
for Niagara-7.
(sparc_fixed_condition_code_regs): New function.
(select_cc_mode): Remove ATTRIBUTE_UNUSED. Adjust for CCNZ/CCXNZ
renaming and add support for CCC/CCXC.
(output_cbranch): Likewise.
(sparc_print_operand): Likewise.
(gen_v9_scc): Remove obsolete assertion.
(emit_scc_insn): Emit RTL directly for EQ and NE. Add direct support
for EQ in DImode if TARGET_SUBXC. Remove test on TARGET_VIS3 for GEU.
(output_cbcond): Remove bogus handling of CC modes.
(sparc_register_move_cost): Return 100 for NO_REGS.
* config/sparc/sparc.md (W): New mode iterator.
(length): Adjust for noov_compare64_operator renaming.
(cmpsi_sne): New instruction.
(cmpdi_sne): Likewise.
(seqdi_special): Delete.
(seqdi_special): Likewise.
(snesi<P:mode>_special): Likewise.
(snedi_special): Likewise.
(snedi_special_vis3): Likewise.
(snesi patterns): Use W iterator.
(snedi patterns): Likewise. Add TARGET_SUBXC patterns.
(sltu patterns): Likewise.
(sgeu patterns): Likewise.
(scc splitter): Do not split GEU in DImode if TARGET_SUBXC.
(normal_branch): Use icc_comparison_operator predicate.
(inverted_branch): Likewise.
(cbcond_sp32): Use comparison_operator predicate.
(cbcond_sp64): Likewise.
(normal_int_branch_sp64): Adjust for renaming
(inverted_int_branch_sp64): Likewise.
(mov<I:mode>_cc_reg_sp64): Likewise.
(movsf_cc_reg_sp6): Likewise.
(movdf_cc_reg_sp64): Likewise.
(movtf_cc_reg_hq_sp64): Likewise.
(movtf_cc_reg_sp64): Likewise.
(mov<I:mode>_cc_v9): Use icc_or_fcc_comparison_operator predicate.
(movsf_cc_v9): Likewise.
(movdf_cc_v9): Likewise.
(movtf_cc_hq_v9): Likewise.
(movtf_cc_v9): Likewise.
(adddi3): Call gen_adddi3_sp32.
(adddi3_insn_sp32): Rename to...
(adddi3_sp32): ...this. Accept only register_operand as operand #1
and use CCCmode for the carry.
(addx_extend_sp32): Use CCCmode for the carry.
(addx_extend_sp64): Delete.
(adddi3_extend_sp32): Use CCCmode for the carry.
(cmp_plus patterns): Use CCNZ/CCXNZ mode and add C variants.
(subdi3): Call gen_subdi3_sp32.
(subdi3_insn_sp32): Rename to...
(subdi3_sp32): ...this and use CCmode for the carry.
(subx_extend_sp32): Use CCCmode for the carry.
(subx_extend_sp64): Delete.
(subdi3_extend_sp32): Use CCmode for the carry.
(cmp_minus patterns): Use CCNZ/CCXNZ mode and add C variants.
(negdi3): Call gen_negdi3_sp32.
(negdi3_sp32): Use CCCmode for the carry.
(cmp_neg patterns): Use CCNZ/CCXNZ mode and add C variants.
(cmp_nz_ashift_1): Use CCNZ mode.
(cmp_nz_set_ashift_1): Likewise.
(ctrapsi4): Use comparison_operator predicate.
(ctrapdi4): Likewise.
(trapsi_insn): Use icc_comparison_operator predicate.
(trapdi_insn): Likewise.
(edge8 patterns): Use CCNZmode.
(edge16 patterns): Likewise.
(edge32 patterns): Likewise.
2016-10-11 Eric Botcazou <ebotcazou@adacore.com> 2016-10-11 Eric Botcazou <ebotcazou@adacore.com>
* config/visium/visium-modes.def (CC_NOOV): Rename into... * config/visium/visium-modes.def (CC_NOOV): Rename into...

View File

@ -234,53 +234,23 @@
;; Return true if OP is a floating point condition code register. ;; Return true if OP is a floating point condition code register.
(define_predicate "fcc_register_operand" (define_predicate "fcc_register_operand"
(match_code "reg") (and (match_code "reg")
{ (match_test "((unsigned) REGNO (op) - SPARC_FIRST_V9_FCC_REG) < 4")))
if (mode != VOIDmode && mode != GET_MODE (op))
return false;
if (mode == VOIDmode
&& (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
return false;
#if 0 /* ??? 1 when %fcc0-3 are pseudos first. See gen_compare_reg(). */
if (reg_renumber == 0)
return REGNO (op) >= FIRST_PSEUDO_REGISTER;
return REGNO_OK_FOR_CCFP_P (REGNO (op));
#else
return ((unsigned) REGNO (op) - SPARC_FIRST_V9_FCC_REG) < 4;
#endif
})
;; Return true if OP is the floating point condition code register fcc0. ;; Return true if OP is the floating point condition code register fcc0.
(define_predicate "fcc0_register_operand" (define_predicate "fcc0_register_operand"
(match_code "reg") (and (match_code "reg")
{ (match_test "REGNO (op) == SPARC_FCC_REG")))
if (mode != VOIDmode && mode != GET_MODE (op))
return false;
if (mode == VOIDmode
&& (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
return false;
return REGNO (op) == SPARC_FCC_REG; ;; Return true if OP is an integer condition code register.
}) (define_predicate "icc_register_operand"
(and (match_code "reg")
(match_test "REGNO (op) == SPARC_ICC_REG")))
;; Return true if OP is an integer or floating point condition code register. ;; Return true if OP is an integer or floating point condition code register.
(define_predicate "icc_or_fcc_register_operand" (define_predicate "icc_or_fcc_register_operand"
(match_code "reg") (ior (match_operand 0 "icc_register_operand")
{ (match_operand 0 "fcc_register_operand")))
if (REGNO (op) == SPARC_ICC_REG)
{
if (mode != VOIDmode && mode != GET_MODE (op))
return false;
if (mode == VOIDmode
&& GET_MODE (op) != CCmode && GET_MODE (op) != CCXmode)
return false;
return true;
}
return fcc_register_operand (op, mode);
})
;; Predicates for arithmetic instructions. ;; Predicates for arithmetic instructions.
@ -442,46 +412,74 @@
;; Predicates for operators. ;; Predicates for operators.
;; Return true if OP is a comparison operator. This allows the use of ;; Return true if OP is a valid comparison operator for CCNZmode.
;; MATCH_OPERATOR to recognize all the branch insns. (define_predicate "nz_comparison_operator"
(define_predicate "noov_compare_operator" (match_code "eq,ne,lt,ge"))
(match_code "ne,eq,ge,gt,le,lt,geu,gtu,leu,ltu")
;; Return true if OP is a valid comparison operator for CCCmode.
(define_predicate "c_comparison_operator"
(match_code "ltu,geu"))
;; Return true if OP is an integer comparison operator. This allows
;; the use of MATCH_OPERATOR to recognize all the branch insns.
(define_predicate "icc_comparison_operator"
(match_operand 0 "ordered_comparison_operator")
{ {
enum rtx_code code = GET_CODE (op); switch (GET_MODE (XEXP (op, 0)))
if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode {
|| GET_MODE (XEXP (op, 0)) == CCX_NOOVmode) case CCmode:
/* These are the only branches which work with CC_NOOVmode. */ case CCXmode:
return (code == EQ || code == NE || code == GE || code == LT); return true;
return true; case CCNZmode:
case CCXNZmode:
return nz_comparison_operator (op, mode);
case CCCmode:
case CCXCmode:
return c_comparison_operator (op, mode);
default:
return false;
}
}) })
;; Return true if OP is a 64-bit comparison operator. This allows the use of ;; Return true if OP is a FP comparison operator.
;; MATCH_OPERATOR to recognize all the branch insns. (define_predicate "fcc_comparison_operator"
(define_predicate "noov_compare64_operator" (match_operand 0 "comparison_operator")
(and (match_code "ne,eq,ge,gt,le,lt,geu,gtu,leu,ltu")
(match_test "TARGET_V9"))
{ {
enum rtx_code code = GET_CODE (op); switch (GET_MODE (XEXP (op, 0)))
if (GET_MODE (XEXP (op, 0)) == CCX_NOOVmode) {
/* These are the only branches which work with CCX_NOOVmode. */ case CCFPmode:
return (code == EQ || code == NE || code == GE || code == LT); case CCFPEmode:
return (GET_MODE (XEXP (op, 0)) == CCXmode); return true;
default:
return false;
}
}) })
;; Return true if OP is an integer or FP comparison operator. This allows
;; the use of MATCH_OPERATOR to recognize all the conditional move insns.
(define_predicate "icc_or_fcc_comparison_operator"
(ior (match_operand 0 "icc_comparison_operator")
(match_operand 0 "fcc_comparison_operator")))
;; Return true if OP is an integer comparison operator for V9.
(define_predicate "v9_comparison_operator"
(and (match_operand 0 "ordered_comparison_operator")
(match_test "TARGET_V9")))
;; Return true if OP is a comparison operator suitable for use in V9 ;; Return true if OP is a comparison operator suitable for use in V9
;; conditional move or branch on register contents instructions. ;; conditional move or branch on register contents instructions.
(define_predicate "v9_register_compare_operator" (define_predicate "v9_register_comparison_operator"
(match_code "eq,ne,ge,lt,le,gt")) (match_code "eq,ne,ge,lt,le,gt"))
;; Return true if OP is an operator which can set the condition codes ;; Return true if OP is an operator which can set the condition codes
;; explicitly. We do not include PLUS and MINUS because these ;; explicitly. We do not include PLUS/MINUS/NEG/ASHIFT because these
;; require CC_NOOVmode, which we handle explicitly. ;; require CCNZmode, which we handle explicitly.
(define_predicate "cc_arith_operator" (define_predicate "cc_arith_operator"
(match_code "and,ior,xor")) (match_code "and,ior,xor"))
;; Return true if OP is an operator which can bitwise complement its ;; Return true if OP is an operator which can bitwise complement its
;; second operand and set the condition codes explicitly. ;; second operand and set the condition codes explicitly.
;; XOR is not here because combine canonicalizes (xor (not ...) ...) ;; XOR is not here because combine canonicalizes (xor (not ...) ...)
;; and (xor ... (not ...)) to (not (xor ...)). */ ;; and (xor ... (not ...)) to (not (xor ...)).
(define_predicate "cc_arith_not_operator" (define_predicate "cc_arith_not_operator"
(match_code "and,ior")) (match_code "and,ior"))

View File

@ -1,7 +1,7 @@
/* Definitions of target machine for GCC, for Sun SPARC. /* Definitions of target machine for GCC, for Sun SPARC.
Copyright (C) 2002-2016 Free Software Foundation, Inc. Copyright (C) 2002-2016 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com). Contributed by Michael Tiemann (tiemann@cygnus.com).
64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans, 64-bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support. at Cygnus Support.
This file is part of GCC. This file is part of GCC.
@ -25,20 +25,27 @@ FLOAT_MODE (TF, 16, ieee_quad_format);
/* Add any extra modes needed to represent the condition code. /* Add any extra modes needed to represent the condition code.
On the SPARC, we have a "no-overflow" mode which is used when an add or We have a CCNZ mode which is used for implicit comparisons with zero when
subtract insn is used to set the condition code. Different branches are arithmetic instructions set the condition code. Only the N and Z flags
used in this case for some operations. are valid in this mode, which means that only the =,!= and <,>= operators
can be used in conjunction with it.
We also have a CCCmode which is used by the arithmetic instructions when
they explicitly set the C flag (unsigned overflow). Only the unsigned
<,>= operators can be used in conjunction with it.
We also have two modes to indicate that the relevant condition code is We also have two modes to indicate that the relevant condition code is
in the floating-point condition code register. One for comparisons which in the floating-point condition code register. One for comparisons which
will generate an exception if the result is unordered (CCFPEmode) and will generate an exception if the result is unordered (CCFPEmode) and
one for comparisons which will never trap (CCFPmode). one for comparisons which will never trap (CCFPmode).
CCXmode and CCX_NOOVmode are only used by v9. */ CC modes are used for the 32-bit ICC, CCX modes for the 64-bit XCC. */
CC_MODE (CCX); CC_MODE (CCX);
CC_MODE (CC_NOOV); CC_MODE (CCNZ);
CC_MODE (CCX_NOOV); CC_MODE (CCXNZ);
CC_MODE (CCC);
CC_MODE (CCXC);
CC_MODE (CCFP); CC_MODE (CCFP);
CC_MODE (CCFPE); CC_MODE (CCFPE);

View File

@ -647,6 +647,7 @@ static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
secondary_reload_info *); secondary_reload_info *);
static machine_mode sparc_cstore_mode (enum insn_code icode); static machine_mode sparc_cstore_mode (enum insn_code icode);
static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *); static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
#ifdef SUBTARGET_ATTRIBUTE_TABLE #ifdef SUBTARGET_ATTRIBUTE_TABLE
/* Table of valid machine attributes. */ /* Table of valid machine attributes. */
@ -857,6 +858,9 @@ char sparc_hard_reg_printed[8];
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV sparc_atomic_assign_expand_fenv #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV sparc_atomic_assign_expand_fenv
#undef TARGET_FIXED_CONDITION_CODE_REGS
#define TARGET_FIXED_CONDITION_CODE_REGS sparc_fixed_condition_code_regs
struct gcc_target targetm = TARGET_INITIALIZER; struct gcc_target targetm = TARGET_INITIALIZER;
/* Return the memory reference contained in X if any, zero otherwise. */ /* Return the memory reference contained in X if any, zero otherwise. */
@ -1314,13 +1318,13 @@ sparc_option_override (void)
MASK_V9|MASK_POPC|MASK_VIS2 }, MASK_V9|MASK_POPC|MASK_VIS2 },
/* UltraSPARC T3 */ /* UltraSPARC T3 */
{ "niagara3", MASK_ISA, { "niagara3", MASK_ISA,
MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF }, MASK_V9|MASK_POPC|MASK_VIS3|MASK_FMAF },
/* UltraSPARC T4 */ /* UltraSPARC T4 */
{ "niagara4", MASK_ISA, { "niagara4", MASK_ISA,
MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF|MASK_CBCOND }, MASK_V9|MASK_POPC|MASK_VIS3|MASK_FMAF|MASK_CBCOND },
/* UltraSPARC M7 */ /* UltraSPARC M7 */
{ "niagara7", MASK_ISA, { "niagara7", MASK_ISA,
MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_VIS4|MASK_FMAF|MASK_CBCOND }, MASK_V9|MASK_POPC|MASK_VIS4|MASK_FMAF|MASK_CBCOND|MASK_SUBXC }
}; };
const struct cpu_table *cpu; const struct cpu_table *cpu;
unsigned int i; unsigned int i;
@ -1451,7 +1455,7 @@ sparc_option_override (void)
& ~MASK_CBCOND & ~MASK_CBCOND
#endif #endif
#ifndef HAVE_AS_SPARC5_VIS4 #ifndef HAVE_AS_SPARC5_VIS4
& ~MASK_VIS4 & ~(MASK_VIS4 | MASK_SUBXC)
#endif #endif
#ifndef HAVE_AS_LEON #ifndef HAVE_AS_LEON
& ~(MASK_LEON | MASK_LEON3) & ~(MASK_LEON | MASK_LEON3)
@ -2742,14 +2746,24 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits); sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
} }
/* Implement TARGET_FIXED_CONDITION_CODE_REGS. */
static bool
sparc_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
{
*p1 = SPARC_ICC_REG;
*p2 = SPARC_FCC_REG;
return true;
}
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point, return the mode to be used for the comparison. For floating-point,
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand CCFP[E]mode is used. CCNZmode should be used when the first operand
is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
processing is needed. */ processing is needed. */
machine_mode machine_mode
select_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED) select_cc_mode (enum rtx_code op, rtx x, rtx y)
{ {
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
{ {
@ -2781,12 +2795,21 @@ select_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED)
|| GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT) || GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT)
{ {
if (TARGET_ARCH64 && GET_MODE (x) == DImode) if (TARGET_ARCH64 && GET_MODE (x) == DImode)
return CCX_NOOVmode; return CCXNZmode;
else else
return CC_NOOVmode; return CCNZmode;
} }
else else
{ {
/* This is for the cmp<mode>_sne pattern. */
if (GET_CODE (x) == NOT && y == constm1_rtx)
{
if (TARGET_ARCH64 && GET_MODE (x) == DImode)
return CCXCmode;
else
return CCCmode;
}
if (TARGET_ARCH64 && GET_MODE (x) == DImode) if (TARGET_ARCH64 && GET_MODE (x) == DImode)
return CCXmode; return CCXmode;
else else
@ -2951,9 +2974,6 @@ gen_v9_scc (rtx dest, enum rtx_code compare_code, rtx x, rtx y)
x = gen_compare_reg_1 (compare_code, x, y); x = gen_compare_reg_1 (compare_code, x, y);
y = const0_rtx; y = const0_rtx;
gcc_assert (GET_MODE (x) != CC_NOOVmode
&& GET_MODE (x) != CCX_NOOVmode);
emit_insn (gen_rtx_SET (dest, const0_rtx)); emit_insn (gen_rtx_SET (dest, const0_rtx));
emit_insn (gen_rtx_SET (dest, emit_insn (gen_rtx_SET (dest,
gen_rtx_IF_THEN_ELSE (GET_MODE (dest), gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
@ -2971,10 +2991,9 @@ gen_v9_scc (rtx dest, enum rtx_code compare_code, rtx x, rtx y)
bool bool
emit_scc_insn (rtx operands[]) emit_scc_insn (rtx operands[])
{ {
rtx tem; rtx tem, x, y;
rtx x;
rtx y;
enum rtx_code code; enum rtx_code code;
machine_mode mode;
/* The quad-word fp compare library routines all return nonzero to indicate /* The quad-word fp compare library routines all return nonzero to indicate
true, which is different from the equivalent libgcc routines, so we must true, which is different from the equivalent libgcc routines, so we must
@ -2990,59 +3009,42 @@ emit_scc_insn (rtx operands[])
code = GET_CODE (operands[1]); code = GET_CODE (operands[1]);
x = operands[2]; x = operands[2];
y = operands[3]; y = operands[3];
mode = GET_MODE (x);
/* For seq/sne on v9 we use the same code as v8 (the addx/subx method has /* For seq/sne on v9 we use the same code as v8 (the addx/subx method has
more applications). The exception to this is "reg != 0" which can more applications). The exception to this is "reg != 0" which can
be done in one instruction on v9 (so we do it). */ be done in one instruction on v9 (so we do it). */
if (code == EQ) if ((code == EQ || code == NE) && (mode == SImode || mode == DImode))
{ {
if (GET_MODE (x) == SImode) if (y != const0_rtx)
{ x = force_reg (mode, gen_rtx_XOR (mode, x, y));
rtx pat;
if (TARGET_ARCH64) rtx pat = gen_rtx_SET (operands[0],
pat = gen_seqsidi_special (operands[0], x, y); gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
else x, const0_rtx));
pat = gen_seqsisi_special (operands[0], x, y);
emit_insn (pat); /* If we can use addx/subx or addxc/subxc, add a clobber for CC. */
return true; if (mode == SImode
} || (code == NE && TARGET_VIS3)
else if (GET_MODE (x) == DImode) || (code == EQ && TARGET_SUBXC))
{ {
rtx pat = gen_seqdi_special (operands[0], x, y); rtx clobber
emit_insn (pat); = gen_rtx_CLOBBER (VOIDmode,
return true; gen_rtx_REG (mode == SImode ? CCmode : CCXmode,
} SPARC_ICC_REG));
pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clobber));
}
emit_insn (pat);
return true;
} }
if (code == NE) /* We can do LTU in DImode using the addxc instruction with VIS3
{ and GEU in DImode using the subxc instruction with SUBXC. */
if (GET_MODE (x) == SImode) if (TARGET_ARCH64
{ && mode == DImode
rtx pat; && !((code == LTU || code == GTU) && TARGET_VIS3)
if (TARGET_ARCH64) && !((code == GEU || code == LEU) && TARGET_SUBXC)
pat = gen_snesidi_special (operands[0], x, y);
else
pat = gen_snesisi_special (operands[0], x, y);
emit_insn (pat);
return true;
}
else if (GET_MODE (x) == DImode)
{
rtx pat;
if (TARGET_VIS3)
pat = gen_snedi_special_vis3 (operands[0], x, y);
else
pat = gen_snedi_special (operands[0], x, y);
emit_insn (pat);
return true;
}
}
if (TARGET_V9
&& TARGET_ARCH64
&& GET_MODE (x) == DImode
&& !(TARGET_VIS3
&& (code == GTU || code == LTU))
&& gen_v9_scc (operands[0], code, x, y)) && gen_v9_scc (operands[0], code, x, y))
return true; return true;
@ -3061,8 +3063,7 @@ emit_scc_insn (rtx operands[])
} }
} }
if (code == LTU if (code == LTU || code == GEU)
|| (!TARGET_VIS3 && code == GEU))
{ {
emit_insn (gen_rtx_SET (operands[0], emit_insn (gen_rtx_SET (operands[0],
gen_rtx_fmt_ee (code, GET_MODE (operands[0]), gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
@ -7715,7 +7716,6 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
case LTGT: case LTGT:
branch = "fblg"; branch = "fblg";
break; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
@ -7741,7 +7741,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
branch = "be"; branch = "be";
break; break;
case GE: case GE:
if (mode == CC_NOOVmode || mode == CCX_NOOVmode) if (mode == CCNZmode || mode == CCXNZmode)
branch = "bpos"; branch = "bpos";
else else
branch = "bge"; branch = "bge";
@ -7753,7 +7753,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
branch = "ble"; branch = "ble";
break; break;
case LT: case LT:
if (mode == CC_NOOVmode || mode == CCX_NOOVmode) if (mode == CCNZmode || mode == CCXNZmode)
branch = "bneg"; branch = "bneg";
else else
branch = "bl"; branch = "bl";
@ -7770,7 +7770,6 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
case LTU: case LTU:
branch = "blu"; branch = "blu";
break; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
@ -7801,28 +7800,37 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
v8 = 1; v8 = 1;
} }
if (mode == CCFPmode || mode == CCFPEmode) switch (mode)
{
static char v9_fcc_labelno[] = "%%fccX, ";
/* Set the char indicating the number of the fcc reg to use. */
v9_fcc_labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
labelno = v9_fcc_labelno;
if (v8)
{
gcc_assert (REGNO (cc_reg) == SPARC_FCC_REG);
labelno = "";
}
}
else if (mode == CCXmode || mode == CCX_NOOVmode)
{
labelno = "%%xcc, ";
gcc_assert (! v8);
}
else
{ {
case CCmode:
case CCNZmode:
case CCCmode:
labelno = "%%icc, "; labelno = "%%icc, ";
if (v8) if (v8)
labelno = ""; labelno = "";
break;
case CCXmode:
case CCXNZmode:
case CCXCmode:
labelno = "%%xcc, ";
gcc_assert (!v8);
break;
case CCFPmode:
case CCFPEmode:
{
static char v9_fcc_labelno[] = "%%fccX, ";
/* Set the char indicating the number of the fcc reg to use. */
v9_fcc_labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
labelno = v9_fcc_labelno;
if (v8)
{
gcc_assert (REGNO (cc_reg) == SPARC_FCC_REG);
labelno = "";
}
}
break;
default:
gcc_unreachable ();
} }
if (*labelno && insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX))) if (*labelno && insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
@ -8129,10 +8137,7 @@ output_cbcond (rtx op, rtx dest, rtx_insn *insn)
break; break;
case GE: case GE:
if (mode == CC_NOOVmode || mode == CCX_NOOVmode) cond_str = "ge";
cond_str = "pos";
else
cond_str = "ge";
break; break;
case GT: case GT:
@ -8144,10 +8149,7 @@ output_cbcond (rtx op, rtx dest, rtx_insn *insn)
break; break;
case LT: case LT:
if (mode == CC_NOOVmode || mode == CCX_NOOVmode) cond_str = "l";
cond_str = "neg";
else
cond_str = "l";
break; break;
case GEU: case GEU:
@ -8699,6 +8701,8 @@ sparc_print_operand_punct_valid_p (unsigned char code)
static void static void
sparc_print_operand (FILE *file, rtx x, int code) sparc_print_operand (FILE *file, rtx x, int code)
{ {
const char *s;
switch (code) switch (code)
{ {
case '#': case '#':
@ -8806,14 +8810,22 @@ sparc_print_operand (FILE *file, rtx x, int code)
/* Print a condition code register. */ /* Print a condition code register. */
if (REGNO (x) == SPARC_ICC_REG) if (REGNO (x) == SPARC_ICC_REG)
{ {
/* We don't handle CC[X]_NOOVmode because they're not supposed switch (GET_MODE (x))
to occur here. */ {
if (GET_MODE (x) == CCmode) case CCmode:
fputs ("%icc", file); case CCNZmode:
else if (GET_MODE (x) == CCXmode) case CCCmode:
fputs ("%xcc", file); s = "%icc";
else break;
gcc_unreachable (); case CCXmode:
case CCXNZmode:
case CCXCmode:
s = "%xcc";
break;
default:
gcc_unreachable ();
}
fputs (s, file);
} }
else else
/* %fccN register */ /* %fccN register */
@ -8838,67 +8850,147 @@ sparc_print_operand (FILE *file, rtx x, int code)
case 'A': case 'A':
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
case IOR: fputs ("or", file); break; case IOR:
case AND: fputs ("and", file); break; s = "or";
case XOR: fputs ("xor", file); break; break;
default: output_operand_lossage ("invalid %%A operand"); case AND:
s = "and";
break;
case XOR:
s = "xor";
break;
default:
output_operand_lossage ("invalid %%A operand");
s = "";
break;
} }
fputs (s, file);
return; return;
case 'B': case 'B':
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
case IOR: fputs ("orn", file); break; case IOR:
case AND: fputs ("andn", file); break; s = "orn";
case XOR: fputs ("xnor", file); break; break;
default: output_operand_lossage ("invalid %%B operand"); case AND:
s = "andn";
break;
case XOR:
s = "xnor";
break;
default:
output_operand_lossage ("invalid %%B operand");
s = "";
break;
} }
fputs (s, file);
return; return;
/* This is used by the conditional move instructions. */ /* This is used by the conditional move instructions. */
case 'C': case 'C':
{ {
enum rtx_code rc = GET_CODE (x); machine_mode mode = GET_MODE (XEXP (x, 0));
switch (GET_CODE (x))
switch (rc)
{ {
case NE: fputs ("ne", file); break; case NE:
case EQ: fputs ("e", file); break; s = "ne";
case GE: fputs ("ge", file); break; break;
case GT: fputs ("g", file); break; case EQ:
case LE: fputs ("le", file); break; s = "e";
case LT: fputs ("l", file); break; break;
case GEU: fputs ("geu", file); break; case GE:
case GTU: fputs ("gu", file); break; if (mode == CCNZmode || mode == CCXNZmode)
case LEU: fputs ("leu", file); break; s = "pos";
case LTU: fputs ("lu", file); break; else
case LTGT: fputs ("lg", file); break; s = "ge";
case UNORDERED: fputs ("u", file); break; break;
case ORDERED: fputs ("o", file); break; case GT:
case UNLT: fputs ("ul", file); break; s = "g";
case UNLE: fputs ("ule", file); break; break;
case UNGT: fputs ("ug", file); break; case LE:
case UNGE: fputs ("uge", file); break; s = "le";
case UNEQ: fputs ("ue", file); break; break;
default: output_operand_lossage ("invalid %%C operand"); case LT:
if (mode == CCNZmode || mode == CCXNZmode)
s = "neg";
else
s = "l";
break;
case GEU:
s = "geu";
break;
case GTU:
s = "gu";
break;
case LEU:
s = "leu";
break;
case LTU:
s = "lu";
break;
case LTGT:
s = "lg";
break;
case UNORDERED:
s = "u";
break;
case ORDERED:
s = "o";
break;
case UNLT:
s = "ul";
break;
case UNLE:
s = "ule";
break;
case UNGT:
s = "ug";
break;
case UNGE:
s = "uge"
; break;
case UNEQ:
s = "ue";
break;
default:
output_operand_lossage ("invalid %%C operand");
s = "";
break;
} }
fputs (s, file);
return; return;
} }
/* This are used by the movr instruction pattern. */ /* This are used by the movr instruction pattern. */
case 'D': case 'D':
{ {
enum rtx_code rc = GET_CODE (x); switch (GET_CODE (x))
switch (rc)
{ {
case NE: fputs ("ne", file); break; case NE:
case EQ: fputs ("e", file); break; s = "ne";
case GE: fputs ("gez", file); break; break;
case LT: fputs ("lz", file); break; case EQ:
case LE: fputs ("lez", file); break; s = "e";
case GT: fputs ("gz", file); break; break;
default: output_operand_lossage ("invalid %%D operand"); case GE:
s = "gez";
break;
case LT:
s = "lz";
break;
case LE:
s = "lez";
break;
case GT:
s = "gz";
break;
default:
output_operand_lossage ("invalid %%D operand");
s = "";
break;
} }
fputs (s, file);
return; return;
} }
@ -11238,6 +11330,10 @@ sparc_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
{ {
bool need_memory = false; bool need_memory = false;
/* This helps postreload CSE to eliminate redundant comparisons. */
if (from == NO_REGS || to == NO_REGS)
return 100;
if (from == FPCC_REGS || to == FPCC_REGS) if (from == FPCC_REGS || to == FPCC_REGS)
need_memory = true; need_memory = true;
else if ((FP_REG_CLASS_P (from) && general_or_i64_p (to)) else if ((FP_REG_CLASS_P (from) && general_or_i64_p (to))

View File

@ -1517,7 +1517,7 @@ do { \
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point, return the mode to be used for the comparison. For floating-point,
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand CCFP[E]mode is used. CCNZmode should be used when the first operand
is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
processing is needed. */ processing is needed. */
#define SELECT_CC_MODE(OP,X,Y) select_cc_mode ((OP), (X), (Y)) #define SELECT_CC_MODE(OP,X,Y) select_cc_mode ((OP), (X), (Y))

File diff suppressed because it is too large Load Diff

View File

@ -89,6 +89,10 @@ mpopc
Target Report Mask(POPC) Target Report Mask(POPC)
Use UltraSPARC Population-Count instruction. Use UltraSPARC Population-Count instruction.
msubxc
Target Report Mask(SUBXC)
Use UltraSPARC Subtract-Extended-with-Carry instruction.
mptr64 mptr64
Target Report RejectNegative Mask(PTR64) Target Report RejectNegative Mask(PTR64)
Pointers are 64-bit. Pointers are 64-bit.

View File

@ -1092,8 +1092,8 @@ See RS/6000 and PowerPC Options.
-muser-mode -mno-user-mode @gol -muser-mode -mno-user-mode @gol
-mv8plus -mno-v8plus -mvis -mno-vis @gol -mv8plus -mno-v8plus -mvis -mno-vis @gol
-mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol -mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol
-mcbcond -mno-cbcond @gol -mcbcond -mno-cbcond -mfmaf -mno-fmaf @gol
-mfmaf -mno-fmaf -mpopc -mno-popc @gol -mpopc -mno-popc -msubxc -mno-subxc@gol
-mfix-at697f -mfix-ut699} -mfix-at697f -mfix-ut699}
@emph{SPU Options} @emph{SPU Options}
@ -22941,18 +22941,9 @@ also sets @option{-mvis3}, @option{-mvis2} and @option{-mvis}.
@itemx -mno-cbcond @itemx -mno-cbcond
@opindex mcbcond @opindex mcbcond
@opindex mno-cbcond @opindex mno-cbcond
With @option{-mcbcond}, GCC generates code that takes advantage of With @option{-mcbcond}, GCC generates code that takes advantage of the UltraSPARC
compare-and-branch instructions, as defined in the Sparc Architecture 2011. Compare-and-Branch-on-Condition instructions. The default is @option{-mcbcond}
The default is @option{-mcbcond} when targeting a cpu that supports such when targeting a CPU that supports such instructions, such as Niagara-4 and
instructions, such as niagara-4 and later.
@item -mpopc
@itemx -mno-popc
@opindex mpopc
@opindex mno-popc
With @option{-mpopc}, GCC generates code that takes advantage of the UltraSPARC
population count instruction. The default is @option{-mpopc}
when targeting a cpu that supports such instructions, such as Niagara-2 and
later. later.
@item -mfmaf @item -mfmaf
@ -22960,8 +22951,26 @@ later.
@opindex mfmaf @opindex mfmaf
@opindex mno-fmaf @opindex mno-fmaf
With @option{-mfmaf}, GCC generates code that takes advantage of the UltraSPARC With @option{-mfmaf}, GCC generates code that takes advantage of the UltraSPARC
Fused Multiply-Add Floating-point extensions. The default is @option{-mfmaf} Fused Multiply-Add Floating-point instructions. The default is @option{-mfmaf}
when targeting a cpu that supports such instructions, such as Niagara-3 and when targeting a CPU that supports such instructions, such as Niagara-3 and
later.
@item -mpopc
@itemx -mno-popc
@opindex mpopc
@opindex mno-popc
With @option{-mpopc}, GCC generates code that takes advantage of the UltraSPARC
Population Count instruction. The default is @option{-mpopc}
when targeting a CPU that supports such an instruction, such as Niagara-2 and
later.
@item -msubxc
@itemx -mno-subxc
@opindex msubxc
@opindex mno-subxc
With @option{-msubxc}, GCC generates code that takes advantage of the UltraSPARC
Subtract-Extended-with-Carry instruction. The default is @option{-msubxc}
when targeting a CPU that supports such an instruction, such as Niagara-7 and
later. later.
@item -mfix-at697f @item -mfix-at697f

View File

@ -6021,8 +6021,8 @@ the case of the add on the SPARC discussed above, we have the pattern
@smallexample @smallexample
(define_insn "" (define_insn ""
[(set (reg:CC_NOOV 0) [(set (reg:CCNZ 0)
(compare:CC_NOOV (compare:CCNZ
(plus:SI (match_operand:SI 0 "register_operand" "%r") (plus:SI (match_operand:SI 0 "register_operand" "%r")
(match_operand:SI 1 "arith_operand" "rI")) (match_operand:SI 1 "arith_operand" "rI"))
(const_int 0)))] (const_int 0)))]
@ -6031,7 +6031,7 @@ the case of the add on the SPARC discussed above, we have the pattern
@end smallexample @end smallexample
@noindent @noindent
together with a @code{SELECT_CC_MODE} that returns @code{CC_NOOVmode} together with a @code{SELECT_CC_MODE} that returns @code{CCNZmode}
for comparisons whose argument is a @code{plus}: for comparisons whose argument is a @code{plus}:
@smallexample @smallexample
@ -6041,7 +6041,7 @@ for comparisons whose argument is a @code{plus}:
? CCFPEmode : CCFPmode) \ ? CCFPEmode : CCFPmode) \
: ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
|| GET_CODE (X) == NEG || GET_CODE (x) == ASHIFT) \ || GET_CODE (X) == NEG || GET_CODE (x) == ASHIFT) \
? CC_NOOVmode : CCmode)) ? CCNZmode : CCmode))
@end smallexample @end smallexample
Another reason to use modes is to retain information on which operands Another reason to use modes is to retain information on which operands

View File

@ -4443,8 +4443,8 @@ the case of the add on the SPARC discussed above, we have the pattern
@smallexample @smallexample
(define_insn "" (define_insn ""
[(set (reg:CC_NOOV 0) [(set (reg:CCNZ 0)
(compare:CC_NOOV (compare:CCNZ
(plus:SI (match_operand:SI 0 "register_operand" "%r") (plus:SI (match_operand:SI 0 "register_operand" "%r")
(match_operand:SI 1 "arith_operand" "rI")) (match_operand:SI 1 "arith_operand" "rI"))
(const_int 0)))] (const_int 0)))]
@ -4453,7 +4453,7 @@ the case of the add on the SPARC discussed above, we have the pattern
@end smallexample @end smallexample
@noindent @noindent
together with a @code{SELECT_CC_MODE} that returns @code{CC_NOOVmode} together with a @code{SELECT_CC_MODE} that returns @code{CCNZmode}
for comparisons whose argument is a @code{plus}: for comparisons whose argument is a @code{plus}:
@smallexample @smallexample
@ -4463,7 +4463,7 @@ for comparisons whose argument is a @code{plus}:
? CCFPEmode : CCFPmode) \ ? CCFPEmode : CCFPmode) \
: ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
|| GET_CODE (X) == NEG || GET_CODE (x) == ASHIFT) \ || GET_CODE (X) == NEG || GET_CODE (x) == ASHIFT) \
? CC_NOOVmode : CCmode)) ? CCNZmode : CCmode))
@end smallexample @end smallexample
Another reason to use modes is to retain information on which operands Another reason to use modes is to retain information on which operands

View File

@ -1,3 +1,20 @@
2016-10-11 Eric Botcazou <ebotcazou@adacore.com>
* gcc.target/sparc/cbcond-1.c: New test.
* gcc.target/sparc/cbcond-2.c: Likewise.
* gcc.target/sparc/movcc-1.c: Likewise.
* gcc.target/sparc/movcc-2.c: Likewise.
* gcc.target/sparc/setcc-1.c: Adjust.
* gcc.target/sparc/setcc-2.c: Likewise.
* gcc.target/sparc/setcc-3.c: Likewise.
* gcc.target/sparc/setcc-4.c: Likewise.
* gcc.target/sparc/setcc-5.c: Likewise.
* gcc.target/sparc/setcc-6.c: New test.
* gcc.target/sparc/setcc-7.c: Likewise.
* gcc.target/sparc/setcc-8.c: Likewise.
* gcc.target/sparc/setcc-9.c: Likewise.
* gcc.target/sparc/setcc-10.c: Likewise.
2016-10-10 Jeff Law <law@redhat.com> 2016-10-10 Jeff Law <law@redhat.com>
PR tree-optimization/71947 PR tree-optimization/71947

View File

@ -0,0 +1,38 @@
/* { dg-do compile } */
/* { dg-options "-O -mcbcond" } */
extern void foo (void);
extern void bar (void);
void cbcondne (int a)
{
if (a != 0)
foo ();
bar ();
}
void cbconde (int a)
{
if (a == 0)
foo ();
bar ();
}
void cbcondl (int a)
{
if (a < 0)
foo ();
bar ();
}
void cbcondle (int a)
{
if (a <= 0)
foo ();
bar ();
}
/* { dg-final { scan-assembler "cwbe\t%" { target ilp32 } } } */
/* { dg-final { scan-assembler "cwbne\t%" { target ilp32 } } } */
/* { dg-final { scan-assembler "cwbl\t%" } } */
/* { dg-final { scan-assembler "cwble\t%" } } */

View File

@ -0,0 +1,39 @@
/* { dg-do compile } */
/* { dg-options "-O -mcbcond" } */
/* { dg-require-effective-target lp64 } */
extern void foo (void);
extern void bar (void);
void cbcondne (long a)
{
if (a != 0)
foo ();
bar ();
}
void cbconde (long a)
{
if (a == 0)
foo ();
bar ();
}
void cbcondl (long a)
{
if (a < 0)
foo ();
bar ();
}
void cbcondle (long a)
{
if (a <= 0)
foo ();
bar ();
}
/* { dg-final { scan-assembler "cxbe\t%" } } */
/* { dg-final { scan-assembler "cxbne\t%" } } */
/* { dg-final { scan-assembler "cxbl\t%" } } */
/* { dg-final { scan-assembler "cxble\t%" } } */

View File

@ -0,0 +1,30 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
int foo1 (int a)
{
int b = a + 1;
if (b != 0)
return b;
return 1;
}
int foo2 (int a)
{
int b = a + 1;
if (b < 0)
return b;
return 1;
}
int foo3 (int a)
{
int b = a + 1;
if (b >= 0)
return b;
return 1;
}
/* { dg-final { scan-assembler "move\t%" } } */
/* { dg-final { scan-assembler "movpos\t%" } } */
/* { dg-final { scan-assembler "movneg\t%" } } */

View File

@ -0,0 +1,31 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-require-effective-target lp64 } */
long foo1 (long a)
{
long b = a + 1;
if (b != 0)
return b;
return 1;
}
long foo2 (long a)
{
long b = a + 1;
if (b < 0)
return b;
return 1;
}
long foo3 (long a)
{
long b = a + 1;
if (b >= 0)
return b;
return 1;
}
/* { dg-final { scan-assembler "movre\t%" } } */
/* { dg-final { scan-assembler "movrgez\t%" } } */
/* { dg-final { scan-assembler "movrlz\t%" } } */

View File

@ -32,8 +32,7 @@ int gt (unsigned int a, unsigned int b)
} }
/* { dg-final { scan-assembler-times "xor\t%" 2 } } */ /* { dg-final { scan-assembler-times "xor\t%" 2 } } */
/* { dg-final { scan-assembler-times "subcc\t%" 2 } } */
/* { dg-final { scan-assembler-times "addx\t%" 3 } } */ /* { dg-final { scan-assembler-times "addx\t%" 3 } } */
/* { dg-final { scan-assembler-times "subx\t%" 3 } } */ /* { dg-final { scan-assembler-times "subx\t%" 3 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */ /* { dg-final { scan-assembler-times "cmp\t%" 6 } } */
/* { dg-final { scan-assembler-not "sra\t%" { target lp64 } } } */ /* { dg-final { scan-assembler-not "sra\t%" { target lp64 } } } */

View File

@ -32,8 +32,7 @@ int gt (unsigned int a, unsigned int b)
} }
/* { dg-final { scan-assembler-times "xor\t%" 2 } } */ /* { dg-final { scan-assembler-times "xor\t%" 2 } } */
/* { dg-final { scan-assembler-times "subcc\t%" 2 } } */
/* { dg-final { scan-assembler-times "addx\t%" 3 } } */ /* { dg-final { scan-assembler-times "addx\t%" 3 } } */
/* { dg-final { scan-assembler-times "subx\t%" 3 } } */ /* { dg-final { scan-assembler-times "subx\t%" 3 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */ /* { dg-final { scan-assembler-times "cmp\t%" 6 } } */
/* { dg-final { scan-assembler-not "sra\t%" { target lp64 } } } */ /* { dg-final { scan-assembler-not "sra\t%" { target lp64 } } } */

View File

@ -18,7 +18,6 @@ int gt (unsigned long a, unsigned long b)
} }
/* { dg-final { scan-assembler "xor\t%" } } */ /* { dg-final { scan-assembler "xor\t%" } } */
/* { dg-final { scan-assembler "subcc\t%" } } */
/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */ /* { dg-final { scan-assembler-times "addxc\t%" 3 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 2 } } */ /* { dg-final { scan-assembler-times "cmp\t%" 3 } } */
/* { dg-final { scan-assembler-not "sra\t%" } } */ /* { dg-final { scan-assembler-not "sra\t%" } } */

View File

@ -1,44 +1,23 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-require-effective-target lp64 } */ /* { dg-require-effective-target lp64 } */
/* { dg-options "-O1 -mno-vis3" } */ /* { dg-options "-O1 -msubxc" } */
long neq (long a, long b) int eq (long a, long b)
{
return a != b;
}
long eq (long a, long b)
{ {
return a == b; return a == b;
} }
long lt (unsigned long a, unsigned long b) int ge (unsigned long a, unsigned long b)
{
return a < b;
}
long leq (unsigned long a, unsigned long b)
{
return a <= b;
}
long geq (unsigned long a, unsigned long b)
{ {
return a >= b; return a >= b;
} }
long gt (unsigned long a, unsigned long b) int le (unsigned long a, unsigned long b)
{ {
return a > b; return a <= b;
} }
/* { dg-final { scan-assembler-times "xor\t%" 2 } } */ /* { dg-final { scan-assembler "xor\t%" } } */
/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */ /* { dg-final { scan-assembler-times "subxc\t%" 3 } } */
/* { dg-final { scan-assembler-times "movrne\t%" 1 } } */ /* { dg-final { scan-assembler-times "cmp\t%" 3 } } */
/* { dg-final { scan-assembler-times "movre\t%" 1 } } */
/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movleu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movgeu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movgu\t%" 1 } } */
/* { dg-final { scan-assembler-not "sra\t%" } } */ /* { dg-final { scan-assembler-not "sra\t%" } } */
/* { dg-final { scan-assembler-not "and\t%" } } */

View File

@ -1,6 +1,6 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-require-effective-target lp64 } */ /* { dg-require-effective-target lp64 } */
/* { dg-options "-O1 -mvis3" } */ /* { dg-options "-O1 -mno-vis3 -mno-subxc" } */
long neq (long a, long b) long neq (long a, long b)
{ {
@ -34,9 +34,11 @@ long gt (unsigned long a, unsigned long b)
/* { dg-final { scan-assembler-times "xor\t%" 2 } } */ /* { dg-final { scan-assembler-times "xor\t%" 2 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */ /* { dg-final { scan-assembler-times "cmp\t%" 4 } } */
/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */ /* { dg-final { scan-assembler-times "movrne\t%" 1 } } */
/* { dg-final { scan-assembler-times "movre\t%" 1 } } */ /* { dg-final { scan-assembler-times "movre\t%" 1 } } */
/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movleu\t%" 1 } } */ /* { dg-final { scan-assembler-times "movleu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movgeu\t%" 1 } } */ /* { dg-final { scan-assembler-times "movgeu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movgu\t%" 1 } } */
/* { dg-final { scan-assembler-not "sra\t%" } } */ /* { dg-final { scan-assembler-not "sra\t%" } } */
/* { dg-final { scan-assembler-not "and\t%" } } */ /* { dg-final { scan-assembler-not "and\t%" } } */

View File

@ -0,0 +1,40 @@
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-O1 -mvis3 -msubxc" } */
long neq (long a, long b)
{
return a != b;
}
long eq (long a, long b)
{
return a == b;
}
long lt (unsigned long a, unsigned long b)
{
return a < b;
}
long leq (unsigned long a, unsigned long b)
{
return a <= b;
}
long geq (unsigned long a, unsigned long b)
{
return a >= b;
}
long gt (unsigned long a, unsigned long b)
{
return a > b;
}
/* { dg-final { scan-assembler-times "xor\t%" 2 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 6 } } */
/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */
/* { dg-final { scan-assembler-times "subxc\t%" 3 } } */
/* { dg-final { scan-assembler-not "sra\t%" } } */
/* { dg-final { scan-assembler-not "and\t%" } } */

View File

@ -0,0 +1,38 @@
/* { dg-do compile } */
/* { dg-options "-O1" } */
int foo1 (int a, int i)
{
return a + (i != 0);
}
int foo2 (int a, int i)
{
return a - (i != 0);
}
int foo3 (int a, int b, int i)
{
return a + b + (i != 0);
}
int foo4 (int a, int b, int i)
{
return a - b - (i != 0);
}
int foo5 (int a, int i)
{
return a + (i == 0);
}
int foo6 (int a, int i)
{
return a - (i == 0);
}
/* { dg-final { scan-assembler-times "addx\t%" 3 } } */
/* { dg-final { scan-assembler-times "subx\t%" 3 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 6 } } */
/* { dg-final { scan-assembler-not "add\t%" } } */
/* { dg-final { scan-assembler-not "sub\t%" } } */

View File

@ -0,0 +1,39 @@
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-O1 -mno-vis3 -mno-subxc" } */
long foo1 (long a, int i)
{
return a + (i != 0);
}
long foo2 (long a, int i)
{
return a - (i != 0);
}
long foo3 (long a, long b, int i)
{
return a + b + (i != 0);
}
long foo4 (long a, long b, int i)
{
return a - b - (i != 0);
}
long foo5 (long a, int i)
{
return a + (i == 0);
}
long foo6 (long a, int i)
{
return a - (i == 0);
}
/* { dg-final { scan-assembler-times "addx\t%" 3 } } */
/* { dg-final { scan-assembler-times "subx\t%" 3 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 6 } } */
/* { dg-final { scan-assembler-not "add\t%" } } */
/* { dg-final { scan-assembler-not "sub\t%" } } */

View File

@ -0,0 +1,23 @@
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-O1 -mvis3" } */
long foo1 (long a, long i)
{
return a + (i != 0);
}
long foo3 (long a, long b, long i)
{
return a + b + (i != 0);
}
long foo6 (long a, long i)
{
return a - (i == 0);
}
/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 3 } } */
/* { dg-final { scan-assembler-not "add\t%" } } */
/* { dg-final { scan-assembler-not "sub\t%" } } */