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:
parent
8d946ecc46
commit
ff7e7ee099
@ -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>
|
||||
|
||||
* config/visium/visium-modes.def (CC_NOOV): Rename into...
|
||||
|
@ -234,53 +234,23 @@
|
||||
|
||||
;; Return true if OP is a floating point condition code register.
|
||||
(define_predicate "fcc_register_operand"
|
||||
(match_code "reg")
|
||||
{
|
||||
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
|
||||
})
|
||||
(and (match_code "reg")
|
||||
(match_test "((unsigned) REGNO (op) - SPARC_FIRST_V9_FCC_REG) < 4")))
|
||||
|
||||
;; Return true if OP is the floating point condition code register fcc0.
|
||||
(define_predicate "fcc0_register_operand"
|
||||
(match_code "reg")
|
||||
{
|
||||
if (mode != VOIDmode && mode != GET_MODE (op))
|
||||
return false;
|
||||
if (mode == VOIDmode
|
||||
&& (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
|
||||
return false;
|
||||
(and (match_code "reg")
|
||||
(match_test "REGNO (op) == SPARC_FCC_REG")))
|
||||
|
||||
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.
|
||||
(define_predicate "icc_or_fcc_register_operand"
|
||||
(match_code "reg")
|
||||
{
|
||||
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);
|
||||
})
|
||||
(ior (match_operand 0 "icc_register_operand")
|
||||
(match_operand 0 "fcc_register_operand")))
|
||||
|
||||
|
||||
;; Predicates for arithmetic instructions.
|
||||
@ -442,46 +412,74 @@
|
||||
|
||||
;; Predicates for operators.
|
||||
|
||||
;; Return true if OP is a comparison operator. This allows the use of
|
||||
;; MATCH_OPERATOR to recognize all the branch insns.
|
||||
(define_predicate "noov_compare_operator"
|
||||
(match_code "ne,eq,ge,gt,le,lt,geu,gtu,leu,ltu")
|
||||
;; Return true if OP is a valid comparison operator for CCNZmode.
|
||||
(define_predicate "nz_comparison_operator"
|
||||
(match_code "eq,ne,lt,ge"))
|
||||
|
||||
;; 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);
|
||||
if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode
|
||||
|| GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
|
||||
/* These are the only branches which work with CC_NOOVmode. */
|
||||
return (code == EQ || code == NE || code == GE || code == LT);
|
||||
return true;
|
||||
switch (GET_MODE (XEXP (op, 0)))
|
||||
{
|
||||
case CCmode:
|
||||
case CCXmode:
|
||||
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
|
||||
;; MATCH_OPERATOR to recognize all the branch insns.
|
||||
(define_predicate "noov_compare64_operator"
|
||||
(and (match_code "ne,eq,ge,gt,le,lt,geu,gtu,leu,ltu")
|
||||
(match_test "TARGET_V9"))
|
||||
;; Return true if OP is a FP comparison operator.
|
||||
(define_predicate "fcc_comparison_operator"
|
||||
(match_operand 0 "comparison_operator")
|
||||
{
|
||||
enum rtx_code code = GET_CODE (op);
|
||||
if (GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
|
||||
/* These are the only branches which work with CCX_NOOVmode. */
|
||||
return (code == EQ || code == NE || code == GE || code == LT);
|
||||
return (GET_MODE (XEXP (op, 0)) == CCXmode);
|
||||
switch (GET_MODE (XEXP (op, 0)))
|
||||
{
|
||||
case CCFPmode:
|
||||
case CCFPEmode:
|
||||
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
|
||||
;; 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"))
|
||||
|
||||
;; Return true if OP is an operator which can set the condition codes
|
||||
;; explicitly. We do not include PLUS and MINUS because these
|
||||
;; require CC_NOOVmode, which we handle explicitly.
|
||||
;; explicitly. We do not include PLUS/MINUS/NEG/ASHIFT because these
|
||||
;; require CCNZmode, which we handle explicitly.
|
||||
(define_predicate "cc_arith_operator"
|
||||
(match_code "and,ior,xor"))
|
||||
|
||||
;; Return true if OP is an operator which can bitwise complement its
|
||||
;; second operand and set the condition codes explicitly.
|
||||
;; 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"
|
||||
(match_code "and,ior"))
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Definitions of target machine for GCC, for Sun SPARC.
|
||||
Copyright (C) 2002-2016 Free Software Foundation, Inc.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
On the SPARC, we have a "no-overflow" mode which is used when an add or
|
||||
subtract insn is used to set the condition code. Different branches are
|
||||
used in this case for some operations.
|
||||
We have a CCNZ mode which is used for implicit comparisons with zero when
|
||||
arithmetic instructions set the condition code. Only the N and Z flags
|
||||
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
|
||||
in the floating-point condition code register. One for comparisons which
|
||||
will generate an exception if the result is unordered (CCFPEmode) and
|
||||
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 (CC_NOOV);
|
||||
CC_MODE (CCX_NOOV);
|
||||
CC_MODE (CCNZ);
|
||||
CC_MODE (CCXNZ);
|
||||
CC_MODE (CCC);
|
||||
CC_MODE (CCXC);
|
||||
CC_MODE (CCFP);
|
||||
CC_MODE (CCFPE);
|
||||
|
||||
|
@ -647,6 +647,7 @@ static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
|
||||
secondary_reload_info *);
|
||||
static machine_mode sparc_cstore_mode (enum insn_code icode);
|
||||
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
|
||||
/* Table of valid machine attributes. */
|
||||
@ -857,6 +858,9 @@ char sparc_hard_reg_printed[8];
|
||||
#undef TARGET_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;
|
||||
|
||||
/* 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 },
|
||||
/* UltraSPARC T3 */
|
||||
{ "niagara3", MASK_ISA,
|
||||
MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF },
|
||||
MASK_V9|MASK_POPC|MASK_VIS3|MASK_FMAF },
|
||||
/* UltraSPARC T4 */
|
||||
{ "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 */
|
||||
{ "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;
|
||||
unsigned int i;
|
||||
@ -1451,7 +1455,7 @@ sparc_option_override (void)
|
||||
& ~MASK_CBCOND
|
||||
#endif
|
||||
#ifndef HAVE_AS_SPARC5_VIS4
|
||||
& ~MASK_VIS4
|
||||
& ~(MASK_VIS4 | MASK_SUBXC)
|
||||
#endif
|
||||
#ifndef HAVE_AS_LEON
|
||||
& ~(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);
|
||||
}
|
||||
|
||||
/* 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,
|
||||
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
|
||||
processing is needed. */
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
if (TARGET_ARCH64 && GET_MODE (x) == DImode)
|
||||
return CCX_NOOVmode;
|
||||
return CCXNZmode;
|
||||
else
|
||||
return CC_NOOVmode;
|
||||
return CCNZmode;
|
||||
}
|
||||
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)
|
||||
return CCXmode;
|
||||
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);
|
||||
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,
|
||||
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
|
||||
emit_scc_insn (rtx operands[])
|
||||
{
|
||||
rtx tem;
|
||||
rtx x;
|
||||
rtx y;
|
||||
rtx tem, x, y;
|
||||
enum rtx_code code;
|
||||
machine_mode mode;
|
||||
|
||||
/* The quad-word fp compare library routines all return nonzero to indicate
|
||||
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]);
|
||||
x = operands[2];
|
||||
y = operands[3];
|
||||
mode = GET_MODE (x);
|
||||
|
||||
/* 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
|
||||
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)
|
||||
{
|
||||
rtx pat;
|
||||
if (TARGET_ARCH64)
|
||||
pat = gen_seqsidi_special (operands[0], x, y);
|
||||
else
|
||||
pat = gen_seqsisi_special (operands[0], x, y);
|
||||
emit_insn (pat);
|
||||
return true;
|
||||
}
|
||||
else if (GET_MODE (x) == DImode)
|
||||
{
|
||||
rtx pat = gen_seqdi_special (operands[0], x, y);
|
||||
emit_insn (pat);
|
||||
return true;
|
||||
}
|
||||
if (y != const0_rtx)
|
||||
x = force_reg (mode, gen_rtx_XOR (mode, x, y));
|
||||
|
||||
rtx pat = gen_rtx_SET (operands[0],
|
||||
gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
|
||||
x, const0_rtx));
|
||||
|
||||
/* If we can use addx/subx or addxc/subxc, add a clobber for CC. */
|
||||
if (mode == SImode
|
||||
|| (code == NE && TARGET_VIS3)
|
||||
|| (code == EQ && TARGET_SUBXC))
|
||||
{
|
||||
rtx clobber
|
||||
= gen_rtx_CLOBBER (VOIDmode,
|
||||
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)
|
||||
{
|
||||
if (GET_MODE (x) == SImode)
|
||||
{
|
||||
rtx pat;
|
||||
if (TARGET_ARCH64)
|
||||
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))
|
||||
/* We can do LTU in DImode using the addxc instruction with VIS3
|
||||
and GEU in DImode using the subxc instruction with SUBXC. */
|
||||
if (TARGET_ARCH64
|
||||
&& mode == DImode
|
||||
&& !((code == LTU || code == GTU) && TARGET_VIS3)
|
||||
&& !((code == GEU || code == LEU) && TARGET_SUBXC)
|
||||
&& gen_v9_scc (operands[0], code, x, y))
|
||||
return true;
|
||||
|
||||
@ -3061,8 +3063,7 @@ emit_scc_insn (rtx operands[])
|
||||
}
|
||||
}
|
||||
|
||||
if (code == LTU
|
||||
|| (!TARGET_VIS3 && code == GEU))
|
||||
if (code == LTU || code == GEU)
|
||||
{
|
||||
emit_insn (gen_rtx_SET (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:
|
||||
branch = "fblg";
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
@ -7741,7 +7741,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
|
||||
branch = "be";
|
||||
break;
|
||||
case GE:
|
||||
if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
|
||||
if (mode == CCNZmode || mode == CCXNZmode)
|
||||
branch = "bpos";
|
||||
else
|
||||
branch = "bge";
|
||||
@ -7753,7 +7753,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
|
||||
branch = "ble";
|
||||
break;
|
||||
case LT:
|
||||
if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
|
||||
if (mode == CCNZmode || mode == CCXNZmode)
|
||||
branch = "bneg";
|
||||
else
|
||||
branch = "bl";
|
||||
@ -7770,7 +7770,6 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
|
||||
case LTU:
|
||||
branch = "blu";
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
@ -7801,28 +7800,37 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
|
||||
v8 = 1;
|
||||
}
|
||||
|
||||
if (mode == CCFPmode || mode == 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 = "";
|
||||
}
|
||||
}
|
||||
else if (mode == CCXmode || mode == CCX_NOOVmode)
|
||||
{
|
||||
labelno = "%%xcc, ";
|
||||
gcc_assert (! v8);
|
||||
}
|
||||
else
|
||||
switch (mode)
|
||||
{
|
||||
case CCmode:
|
||||
case CCNZmode:
|
||||
case CCCmode:
|
||||
labelno = "%%icc, ";
|
||||
if (v8)
|
||||
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)))
|
||||
@ -8129,10 +8137,7 @@ output_cbcond (rtx op, rtx dest, rtx_insn *insn)
|
||||
break;
|
||||
|
||||
case GE:
|
||||
if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
|
||||
cond_str = "pos";
|
||||
else
|
||||
cond_str = "ge";
|
||||
cond_str = "ge";
|
||||
break;
|
||||
|
||||
case GT:
|
||||
@ -8144,10 +8149,7 @@ output_cbcond (rtx op, rtx dest, rtx_insn *insn)
|
||||
break;
|
||||
|
||||
case LT:
|
||||
if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
|
||||
cond_str = "neg";
|
||||
else
|
||||
cond_str = "l";
|
||||
cond_str = "l";
|
||||
break;
|
||||
|
||||
case GEU:
|
||||
@ -8699,6 +8701,8 @@ sparc_print_operand_punct_valid_p (unsigned char code)
|
||||
static void
|
||||
sparc_print_operand (FILE *file, rtx x, int code)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case '#':
|
||||
@ -8806,14 +8810,22 @@ sparc_print_operand (FILE *file, rtx x, int code)
|
||||
/* Print a condition code register. */
|
||||
if (REGNO (x) == SPARC_ICC_REG)
|
||||
{
|
||||
/* We don't handle CC[X]_NOOVmode because they're not supposed
|
||||
to occur here. */
|
||||
if (GET_MODE (x) == CCmode)
|
||||
fputs ("%icc", file);
|
||||
else if (GET_MODE (x) == CCXmode)
|
||||
fputs ("%xcc", file);
|
||||
else
|
||||
gcc_unreachable ();
|
||||
switch (GET_MODE (x))
|
||||
{
|
||||
case CCmode:
|
||||
case CCNZmode:
|
||||
case CCCmode:
|
||||
s = "%icc";
|
||||
break;
|
||||
case CCXmode:
|
||||
case CCXNZmode:
|
||||
case CCXCmode:
|
||||
s = "%xcc";
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
fputs (s, file);
|
||||
}
|
||||
else
|
||||
/* %fccN register */
|
||||
@ -8838,67 +8850,147 @@ sparc_print_operand (FILE *file, rtx x, int code)
|
||||
case 'A':
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case IOR: fputs ("or", file); break;
|
||||
case AND: fputs ("and", file); break;
|
||||
case XOR: fputs ("xor", file); break;
|
||||
default: output_operand_lossage ("invalid %%A operand");
|
||||
case IOR:
|
||||
s = "or";
|
||||
break;
|
||||
case AND:
|
||||
s = "and";
|
||||
break;
|
||||
case XOR:
|
||||
s = "xor";
|
||||
break;
|
||||
default:
|
||||
output_operand_lossage ("invalid %%A operand");
|
||||
s = "";
|
||||
break;
|
||||
}
|
||||
fputs (s, file);
|
||||
return;
|
||||
|
||||
case 'B':
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case IOR: fputs ("orn", file); break;
|
||||
case AND: fputs ("andn", file); break;
|
||||
case XOR: fputs ("xnor", file); break;
|
||||
default: output_operand_lossage ("invalid %%B operand");
|
||||
case IOR:
|
||||
s = "orn";
|
||||
break;
|
||||
case AND:
|
||||
s = "andn";
|
||||
break;
|
||||
case XOR:
|
||||
s = "xnor";
|
||||
break;
|
||||
default:
|
||||
output_operand_lossage ("invalid %%B operand");
|
||||
s = "";
|
||||
break;
|
||||
}
|
||||
fputs (s, file);
|
||||
return;
|
||||
|
||||
/* This is used by the conditional move instructions. */
|
||||
case 'C':
|
||||
{
|
||||
enum rtx_code rc = GET_CODE (x);
|
||||
|
||||
switch (rc)
|
||||
machine_mode mode = GET_MODE (XEXP (x, 0));
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case NE: fputs ("ne", file); break;
|
||||
case EQ: fputs ("e", file); break;
|
||||
case GE: fputs ("ge", file); break;
|
||||
case GT: fputs ("g", file); break;
|
||||
case LE: fputs ("le", file); break;
|
||||
case LT: fputs ("l", file); break;
|
||||
case GEU: fputs ("geu", file); break;
|
||||
case GTU: fputs ("gu", file); break;
|
||||
case LEU: fputs ("leu", file); break;
|
||||
case LTU: fputs ("lu", file); break;
|
||||
case LTGT: fputs ("lg", file); break;
|
||||
case UNORDERED: fputs ("u", file); break;
|
||||
case ORDERED: fputs ("o", file); break;
|
||||
case UNLT: fputs ("ul", file); break;
|
||||
case UNLE: fputs ("ule", file); break;
|
||||
case UNGT: fputs ("ug", file); break;
|
||||
case UNGE: fputs ("uge", file); break;
|
||||
case UNEQ: fputs ("ue", file); break;
|
||||
default: output_operand_lossage ("invalid %%C operand");
|
||||
case NE:
|
||||
s = "ne";
|
||||
break;
|
||||
case EQ:
|
||||
s = "e";
|
||||
break;
|
||||
case GE:
|
||||
if (mode == CCNZmode || mode == CCXNZmode)
|
||||
s = "pos";
|
||||
else
|
||||
s = "ge";
|
||||
break;
|
||||
case GT:
|
||||
s = "g";
|
||||
break;
|
||||
case LE:
|
||||
s = "le";
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
/* This are used by the movr instruction pattern. */
|
||||
case 'D':
|
||||
{
|
||||
enum rtx_code rc = GET_CODE (x);
|
||||
switch (rc)
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case NE: fputs ("ne", file); break;
|
||||
case EQ: fputs ("e", file); break;
|
||||
case GE: fputs ("gez", file); break;
|
||||
case LT: fputs ("lz", file); break;
|
||||
case LE: fputs ("lez", file); break;
|
||||
case GT: fputs ("gz", file); break;
|
||||
default: output_operand_lossage ("invalid %%D operand");
|
||||
case NE:
|
||||
s = "ne";
|
||||
break;
|
||||
case EQ:
|
||||
s = "e";
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -11238,6 +11330,10 @@ sparc_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
|
||||
{
|
||||
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)
|
||||
need_memory = true;
|
||||
else if ((FP_REG_CLASS_P (from) && general_or_i64_p (to))
|
||||
|
@ -1517,7 +1517,7 @@ do { \
|
||||
|
||||
/* 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,
|
||||
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
|
||||
processing is needed. */
|
||||
#define SELECT_CC_MODE(OP,X,Y) select_cc_mode ((OP), (X), (Y))
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -89,6 +89,10 @@ mpopc
|
||||
Target Report Mask(POPC)
|
||||
Use UltraSPARC Population-Count instruction.
|
||||
|
||||
msubxc
|
||||
Target Report Mask(SUBXC)
|
||||
Use UltraSPARC Subtract-Extended-with-Carry instruction.
|
||||
|
||||
mptr64
|
||||
Target Report RejectNegative Mask(PTR64)
|
||||
Pointers are 64-bit.
|
||||
|
@ -1092,8 +1092,8 @@ See RS/6000 and PowerPC Options.
|
||||
-muser-mode -mno-user-mode @gol
|
||||
-mv8plus -mno-v8plus -mvis -mno-vis @gol
|
||||
-mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol
|
||||
-mcbcond -mno-cbcond @gol
|
||||
-mfmaf -mno-fmaf -mpopc -mno-popc @gol
|
||||
-mcbcond -mno-cbcond -mfmaf -mno-fmaf @gol
|
||||
-mpopc -mno-popc -msubxc -mno-subxc@gol
|
||||
-mfix-at697f -mfix-ut699}
|
||||
|
||||
@emph{SPU Options}
|
||||
@ -22941,18 +22941,9 @@ also sets @option{-mvis3}, @option{-mvis2} and @option{-mvis}.
|
||||
@itemx -mno-cbcond
|
||||
@opindex mcbcond
|
||||
@opindex mno-cbcond
|
||||
With @option{-mcbcond}, GCC generates code that takes advantage of
|
||||
compare-and-branch instructions, as defined in the Sparc Architecture 2011.
|
||||
The default is @option{-mcbcond} when targeting a cpu that supports such
|
||||
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
|
||||
With @option{-mcbcond}, GCC generates code that takes advantage of the UltraSPARC
|
||||
Compare-and-Branch-on-Condition instructions. The default is @option{-mcbcond}
|
||||
when targeting a CPU that supports such instructions, such as Niagara-4 and
|
||||
later.
|
||||
|
||||
@item -mfmaf
|
||||
@ -22960,8 +22951,26 @@ later.
|
||||
@opindex mfmaf
|
||||
@opindex mno-fmaf
|
||||
With @option{-mfmaf}, GCC generates code that takes advantage of the UltraSPARC
|
||||
Fused Multiply-Add Floating-point extensions. The default is @option{-mfmaf}
|
||||
when targeting a cpu that supports such instructions, such as Niagara-3 and
|
||||
Fused Multiply-Add Floating-point instructions. The default is @option{-mfmaf}
|
||||
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.
|
||||
|
||||
@item -mfix-at697f
|
||||
|
@ -6021,8 +6021,8 @@ the case of the add on the SPARC discussed above, we have the pattern
|
||||
|
||||
@smallexample
|
||||
(define_insn ""
|
||||
[(set (reg:CC_NOOV 0)
|
||||
(compare:CC_NOOV
|
||||
[(set (reg:CCNZ 0)
|
||||
(compare:CCNZ
|
||||
(plus:SI (match_operand:SI 0 "register_operand" "%r")
|
||||
(match_operand:SI 1 "arith_operand" "rI"))
|
||||
(const_int 0)))]
|
||||
@ -6031,7 +6031,7 @@ the case of the add on the SPARC discussed above, we have the pattern
|
||||
@end smallexample
|
||||
|
||||
@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}:
|
||||
|
||||
@smallexample
|
||||
@ -6041,7 +6041,7 @@ for comparisons whose argument is a @code{plus}:
|
||||
? CCFPEmode : CCFPmode) \
|
||||
: ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
|
||||
|| GET_CODE (X) == NEG || GET_CODE (x) == ASHIFT) \
|
||||
? CC_NOOVmode : CCmode))
|
||||
? CCNZmode : CCmode))
|
||||
@end smallexample
|
||||
|
||||
Another reason to use modes is to retain information on which operands
|
||||
|
@ -4443,8 +4443,8 @@ the case of the add on the SPARC discussed above, we have the pattern
|
||||
|
||||
@smallexample
|
||||
(define_insn ""
|
||||
[(set (reg:CC_NOOV 0)
|
||||
(compare:CC_NOOV
|
||||
[(set (reg:CCNZ 0)
|
||||
(compare:CCNZ
|
||||
(plus:SI (match_operand:SI 0 "register_operand" "%r")
|
||||
(match_operand:SI 1 "arith_operand" "rI"))
|
||||
(const_int 0)))]
|
||||
@ -4453,7 +4453,7 @@ the case of the add on the SPARC discussed above, we have the pattern
|
||||
@end smallexample
|
||||
|
||||
@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}:
|
||||
|
||||
@smallexample
|
||||
@ -4463,7 +4463,7 @@ for comparisons whose argument is a @code{plus}:
|
||||
? CCFPEmode : CCFPmode) \
|
||||
: ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
|
||||
|| GET_CODE (X) == NEG || GET_CODE (x) == ASHIFT) \
|
||||
? CC_NOOVmode : CCmode))
|
||||
? CCNZmode : CCmode))
|
||||
@end smallexample
|
||||
|
||||
Another reason to use modes is to retain information on which operands
|
||||
|
@ -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>
|
||||
|
||||
PR tree-optimization/71947
|
||||
|
38
gcc/testsuite/gcc.target/sparc/cbcond-1.c
Normal file
38
gcc/testsuite/gcc.target/sparc/cbcond-1.c
Normal 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%" } } */
|
39
gcc/testsuite/gcc.target/sparc/cbcond-2.c
Normal file
39
gcc/testsuite/gcc.target/sparc/cbcond-2.c
Normal 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%" } } */
|
30
gcc/testsuite/gcc.target/sparc/movcc-1.c
Normal file
30
gcc/testsuite/gcc.target/sparc/movcc-1.c
Normal 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%" } } */
|
31
gcc/testsuite/gcc.target/sparc/movcc-2.c
Normal file
31
gcc/testsuite/gcc.target/sparc/movcc-2.c
Normal 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%" } } */
|
@ -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 "subcc\t%" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "addx\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 } } } */
|
||||
|
@ -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 "subcc\t%" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "addx\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 } } } */
|
||||
|
@ -18,7 +18,6 @@ int gt (unsigned long a, unsigned long b)
|
||||
}
|
||||
|
||||
/* { 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 "cmp\t%" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "cmp\t%" 3 } } */
|
||||
/* { dg-final { scan-assembler-not "sra\t%" } } */
|
||||
|
@ -1,44 +1,23 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target lp64 } */
|
||||
/* { dg-options "-O1 -mno-vis3" } */
|
||||
/* { dg-options "-O1 -msubxc" } */
|
||||
|
||||
long neq (long a, long b)
|
||||
{
|
||||
return a != b;
|
||||
}
|
||||
|
||||
long eq (long a, long b)
|
||||
int 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)
|
||||
int ge (unsigned long a, unsigned long 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-times "cmp\t%" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "movrne\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 "movgeu\t%" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "movgu\t%" 1 } } */
|
||||
/* { dg-final { scan-assembler "xor\t%" } } */
|
||||
/* { dg-final { scan-assembler-times "subxc\t%" 3 } } */
|
||||
/* { dg-final { scan-assembler-times "cmp\t%" 3 } } */
|
||||
/* { dg-final { scan-assembler-not "sra\t%" } } */
|
||||
/* { dg-final { scan-assembler-not "and\t%" } } */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target lp64 } */
|
||||
/* { dg-options "-O1 -mvis3" } */
|
||||
/* { dg-options "-O1 -mno-vis3 -mno-subxc" } */
|
||||
|
||||
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 "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 "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 "and\t%" } } */
|
||||
|
40
gcc/testsuite/gcc.target/sparc/setcc-6.c
Normal file
40
gcc/testsuite/gcc.target/sparc/setcc-6.c
Normal 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%" } } */
|
38
gcc/testsuite/gcc.target/sparc/setcc-7.c
Normal file
38
gcc/testsuite/gcc.target/sparc/setcc-7.c
Normal 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%" } } */
|
39
gcc/testsuite/gcc.target/sparc/setcc-8.c
Normal file
39
gcc/testsuite/gcc.target/sparc/setcc-8.c
Normal 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%" } } */
|
23
gcc/testsuite/gcc.target/sparc/setcc-9.c
Normal file
23
gcc/testsuite/gcc.target/sparc/setcc-9.c
Normal 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%" } } */
|
Loading…
Reference in New Issue
Block a user