Commit 5f3bc026 by Zhenqiang Chen Committed by Jiong Wang

[AArch64] Enable CCMP support for AArch64, PR64015 resolved

gcc/
2015-01-16  Zhenqiang Chen  <zhenqiang.chen@arm.com>

	PR target/64015
	* ccmp.c (expand_ccmp_next): New function.
	(expand_ccmp_expr_1, expand_ccmp_expr): Handle operand insn sequence
	and compare insn sequence.
	* config/aarch64/aarch64.c (aarch64_code_to_ccmode,
	aarch64_gen_ccmp_first, aarch64_gen_ccmp_next): New functions.
	(TARGET_GEN_CCMP_FIRST, TARGET_GEN_CCMP_NEXT): New MICRO.
	* config/aarch64/aarch64.md (*ccmp_and): Changed to ccmp_and<mode>.
	(*ccmp_ior): Changed to ccmp_ior<mode>.
	(cmp<mode>): New pattern.
	* doc/tm.texi (TARGET_GEN_CCMP_FIRST, TARGET_GEN_CCMP_NEXT): Update
	parameters.
	* target.def (gen_ccmp_first, gen_ccmp_next): Update parameters.

gcc/testsuite/
2015-01-16  Zhenqiang Chen <zhenqiang.chen@arm.com>

	* gcc.dg/pr64015.c: New test.

From-SVN: r219723
parent fe23ff4b
2015-01-16 Zhenqiang Chen <zhenqiang.chen@arm.com>
PR target/64015
* ccmp.c (expand_ccmp_next): New function.
(expand_ccmp_expr_1, expand_ccmp_expr): Handle operand insn sequence
and compare insn sequence.
* config/aarch64/aarch64.c (aarch64_code_to_ccmode,
aarch64_gen_ccmp_first, aarch64_gen_ccmp_next): New functions.
(TARGET_GEN_CCMP_FIRST, TARGET_GEN_CCMP_NEXT): New MICRO.
* config/aarch64/aarch64.md (*ccmp_and): Changed to ccmp_and<mode>.
(*ccmp_ior): Changed to ccmp_ior<mode>.
(cmp<mode>): New pattern.
* doc/tm.texi (TARGET_GEN_CCMP_FIRST, TARGET_GEN_CCMP_NEXT): Update
parameters.
* target.def (gen_ccmp_first, gen_ccmp_next): Update parameters.
2015-01-16 Ilya Tocar <ilya.tocar@intel.com> 2015-01-16 Ilya Tocar <ilya.tocar@intel.com>
* config/i386/avx2intrin.h (_mm256_bslli_epi128, * config/i386/avx2intrin.h (_mm256_bslli_epi128,
......
...@@ -92,7 +92,16 @@ along with GCC; see the file COPYING3. If not see ...@@ -92,7 +92,16 @@ along with GCC; see the file COPYING3. If not see
* If the final result is not used in a COND_EXPR (checked by function * If the final result is not used in a COND_EXPR (checked by function
used_in_cond_stmt_p), it calls cstorecc4 pattern to store the CC to a used_in_cond_stmt_p), it calls cstorecc4 pattern to store the CC to a
general register. */ general register.
Since the operands of the later compares might clobber CC reg, we do not
emit the insns during expand. We keep the insn sequences in two seq
* prep_seq, which includes all the insns to prepare the operands.
* gen_seq, which includes all the compare and conditional compares.
If all checks OK in expand_ccmp_expr, it emits insns in prep_seq, then
insns in gen_seq. */
/* Check whether G is a potential conditional compare candidate. */ /* Check whether G is a potential conditional compare candidate. */
static bool static bool
...@@ -172,6 +181,27 @@ used_in_cond_stmt_p (tree exp) ...@@ -172,6 +181,27 @@ used_in_cond_stmt_p (tree exp)
return expand_cond; return expand_cond;
} }
/* PREV is the CC flag from precvious compares. The function expands the
next compare based on G which ops previous compare with CODE.
PREP_SEQ returns all insns to prepare opearands for compare.
GEN_SEQ returnss all compare insns. */
static rtx
expand_ccmp_next (gimple g, enum tree_code code, rtx prev,
rtx *prep_seq, rtx *gen_seq)
{
enum rtx_code rcode;
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)));
gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
rcode = get_rtx_code (gimple_assign_rhs_code (g), unsignedp);
return targetm.gen_ccmp_next (prep_seq, gen_seq, prev, rcode,
gimple_assign_rhs1 (g),
gimple_assign_rhs2 (g),
get_rtx_code (code, 0));
}
/* Expand conditional compare gimple G. A typical CCMP sequence is like: /* Expand conditional compare gimple G. A typical CCMP sequence is like:
CC0 = CMP (a, b); CC0 = CMP (a, b);
...@@ -180,9 +210,11 @@ used_in_cond_stmt_p (tree exp) ...@@ -180,9 +210,11 @@ used_in_cond_stmt_p (tree exp)
CCn = CCMP (NE (CCn-1, 0), CMP (...)); CCn = CCMP (NE (CCn-1, 0), CMP (...));
hook gen_ccmp_first is used to expand the first compare. hook gen_ccmp_first is used to expand the first compare.
hook gen_ccmp_next is used to expand the following CCMP. */ hook gen_ccmp_next is used to expand the following CCMP.
PREP_SEQ returns all insns to prepare opearand.
GEN_SEQ returns all compare insns. */
static rtx static rtx
expand_ccmp_expr_1 (gimple g) expand_ccmp_expr_1 (gimple g, rtx *prep_seq, rtx *gen_seq)
{ {
tree exp = gimple_assign_rhs_to_tree (g); tree exp = gimple_assign_rhs_to_tree (g);
enum tree_code code = TREE_CODE (exp); enum tree_code code = TREE_CODE (exp);
...@@ -199,52 +231,27 @@ expand_ccmp_expr_1 (gimple g) ...@@ -199,52 +231,27 @@ expand_ccmp_expr_1 (gimple g)
{ {
if (TREE_CODE_CLASS (code1) == tcc_comparison) if (TREE_CODE_CLASS (code1) == tcc_comparison)
{ {
int unsignedp0, unsignedp1; int unsignedp0;
enum rtx_code rcode0, rcode1; enum rtx_code rcode0;
rtx op0, op1, op2, op3, tmp;
unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0))); unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0)));
rcode0 = get_rtx_code (code0, unsignedp0); rcode0 = get_rtx_code (code0, unsignedp0);
unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs1)));
rcode1 = get_rtx_code (code1, unsignedp1); tmp = targetm.gen_ccmp_first (prep_seq, gen_seq, rcode0,
gimple_assign_rhs1 (gs0),
expand_operands (gimple_assign_rhs1 (gs0), gimple_assign_rhs2 (gs0));
gimple_assign_rhs2 (gs0),
NULL_RTX, &op0, &op1, EXPAND_NORMAL);
/* Since the operands of GS1 might clobber CC reg, we expand the
operands of GS1 before GEN_CCMP_FIRST. */
expand_operands (gimple_assign_rhs1 (gs1),
gimple_assign_rhs2 (gs1),
NULL_RTX, &op2, &op3, EXPAND_NORMAL);
tmp = targetm.gen_ccmp_first (rcode0, op0, op1);
if (!tmp) if (!tmp)
return NULL_RTX; return NULL_RTX;
return targetm.gen_ccmp_next (tmp, rcode1, op2, op3, return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq);
get_rtx_code (code, 0));
} }
else else
{ {
rtx op0, op1; tmp = expand_ccmp_expr_1 (gs1, prep_seq, gen_seq);
enum rtx_code rcode; if (!tmp)
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0))); return NULL_RTX;
rcode = get_rtx_code (gimple_assign_rhs_code (gs0), unsignedp);
/* Hoist the preparation operations above the entire
conditional compare sequence. */
expand_operands (gimple_assign_rhs1 (gs0),
gimple_assign_rhs2 (gs0),
NULL_RTX, &op0, &op1, EXPAND_NORMAL);
gcc_assert (code1 == BIT_AND_EXPR || code1 == BIT_IOR_EXPR);
/* Note: We swap the order to make the recursive function work. */ return expand_ccmp_next (gs0, code, tmp, prep_seq, gen_seq);
tmp = expand_ccmp_expr_1 (gs1);
if (tmp)
return targetm.gen_ccmp_next (tmp, rcode, op0, op1,
get_rtx_code (code, 0));
} }
} }
else else
...@@ -254,21 +261,11 @@ expand_ccmp_expr_1 (gimple g) ...@@ -254,21 +261,11 @@ expand_ccmp_expr_1 (gimple g)
if (TREE_CODE_CLASS (gimple_assign_rhs_code (gs1)) == tcc_comparison) if (TREE_CODE_CLASS (gimple_assign_rhs_code (gs1)) == tcc_comparison)
{ {
rtx op0, op1; tmp = expand_ccmp_expr_1 (gs0, prep_seq, gen_seq);
enum rtx_code rcode; if (!tmp)
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs1))); return NULL_RTX;
rcode = get_rtx_code (gimple_assign_rhs_code (gs1), unsignedp); return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq);
/* Hoist the preparation operations above the entire
conditional compare sequence. */
expand_operands (gimple_assign_rhs1 (gs1),
gimple_assign_rhs2 (gs1),
NULL_RTX, &op0, &op1, EXPAND_NORMAL);
tmp = expand_ccmp_expr_1 (gs0);
if (tmp)
return targetm.gen_ccmp_next (tmp, rcode, op0, op1,
get_rtx_code (code, 0));
} }
else else
{ {
...@@ -288,23 +285,30 @@ expand_ccmp_expr (gimple g) ...@@ -288,23 +285,30 @@ expand_ccmp_expr (gimple g)
{ {
rtx_insn *last; rtx_insn *last;
rtx tmp; rtx tmp;
rtx prep_seq, gen_seq;
prep_seq = gen_seq = NULL_RTX;
if (!ccmp_candidate_p (g)) if (!ccmp_candidate_p (g))
return NULL_RTX; return NULL_RTX;
last = get_last_insn (); last = get_last_insn ();
tmp = expand_ccmp_expr_1 (g); tmp = expand_ccmp_expr_1 (g, &prep_seq, &gen_seq);
if (tmp) if (tmp)
{ {
enum insn_code icode; enum insn_code icode;
enum machine_mode cc_mode = CCmode; enum machine_mode cc_mode = CCmode;
tree lhs = gimple_assign_lhs (g); tree lhs = gimple_assign_lhs (g);
/* TMP should be CC. If it is used in a GIMPLE_COND, just return it. /* TMP should be CC. If it is used in a GIMPLE_COND, just return it.
Note: Target needs to define "cbranchcc4". */ Note: Target needs to define "cbranchcc4". */
if (used_in_cond_stmt_p (lhs)) if (used_in_cond_stmt_p (lhs))
return tmp; {
emit_insn (prep_seq);
emit_insn (gen_seq);
return tmp;
}
#ifdef SELECT_CC_MODE #ifdef SELECT_CC_MODE
cc_mode = SELECT_CC_MODE (NE, tmp, const0_rtx); cc_mode = SELECT_CC_MODE (NE, tmp, const0_rtx);
...@@ -314,9 +318,12 @@ expand_ccmp_expr (gimple g) ...@@ -314,9 +318,12 @@ expand_ccmp_expr (gimple g)
icode = optab_handler (cstore_optab, cc_mode); icode = optab_handler (cstore_optab, cc_mode);
if (icode != CODE_FOR_nothing) if (icode != CODE_FOR_nothing)
{ {
tree lhs = gimple_assign_lhs (g);
enum machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); enum machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
rtx target = gen_reg_rtx (mode); rtx target = gen_reg_rtx (mode);
emit_insn (prep_seq);
emit_insn (gen_seq);
tmp = emit_cstore (target, icode, NE, cc_mode, cc_mode, tmp = emit_cstore (target, icode, NE, cc_mode, cc_mode,
0, tmp, const0_rtx, 1, mode); 0, tmp, const0_rtx, 1, mode);
if (tmp) if (tmp)
......
...@@ -10381,6 +10381,198 @@ aarch64_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, ...@@ -10381,6 +10381,198 @@ aarch64_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
return default_use_by_pieces_infrastructure_p (size, align, op, speed_p); return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
} }
static enum machine_mode
aarch64_code_to_ccmode (enum rtx_code code)
{
switch (code)
{
case NE:
return CC_DNEmode;
case EQ:
return CC_DEQmode;
case LE:
return CC_DLEmode;
case LT:
return CC_DLTmode;
case GE:
return CC_DGEmode;
case GT:
return CC_DGTmode;
case LEU:
return CC_DLEUmode;
case LTU:
return CC_DLTUmode;
case GEU:
return CC_DGEUmode;
case GTU:
return CC_DGTUmode;
default:
return CCmode;
}
}
static rtx
aarch64_gen_ccmp_first (rtx *prep_seq, rtx *gen_seq,
int code, tree treeop0, tree treeop1)
{
enum machine_mode op_mode, cmp_mode, cc_mode;
rtx op0, op1, cmp, target;
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0));
enum insn_code icode;
struct expand_operand ops[4];
cc_mode = aarch64_code_to_ccmode ((enum rtx_code) code);
if (cc_mode == CCmode)
return NULL_RTX;
start_sequence ();
expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
op_mode = GET_MODE (op0);
if (op_mode == VOIDmode)
op_mode = GET_MODE (op1);
switch (op_mode)
{
case QImode:
case HImode:
case SImode:
cmp_mode = SImode;
icode = CODE_FOR_cmpsi;
break;
case DImode:
cmp_mode = DImode;
icode = CODE_FOR_cmpdi;
break;
default:
end_sequence ();
return NULL_RTX;
}
op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp);
op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp);
if (!op0 || !op1)
{
end_sequence ();
return NULL_RTX;
}
*prep_seq = get_insns ();
end_sequence ();
cmp = gen_rtx_fmt_ee ((enum rtx_code) code, cmp_mode, op0, op1);
target = gen_rtx_REG (CCmode, CC_REGNUM);
create_output_operand (&ops[0], target, CCmode);
create_fixed_operand (&ops[1], cmp);
create_fixed_operand (&ops[2], op0);
create_fixed_operand (&ops[3], op1);
start_sequence ();
if (!maybe_expand_insn (icode, 4, ops))
{
end_sequence ();
return NULL_RTX;
}
*gen_seq = get_insns ();
end_sequence ();
return gen_rtx_REG (cc_mode, CC_REGNUM);
}
static rtx
aarch64_gen_ccmp_next (rtx *prep_seq, rtx *gen_seq, rtx prev, int cmp_code,
tree treeop0, tree treeop1, int bit_code)
{
rtx op0, op1, cmp0, cmp1, target;
enum machine_mode op_mode, cmp_mode, cc_mode;
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0));
enum insn_code icode = CODE_FOR_ccmp_andsi;
struct expand_operand ops[6];
cc_mode = aarch64_code_to_ccmode ((enum rtx_code) cmp_code);
if (cc_mode == CCmode)
return NULL_RTX;
push_to_sequence ((rtx_insn*) *prep_seq);
expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
op_mode = GET_MODE (op0);
if (op_mode == VOIDmode)
op_mode = GET_MODE (op1);
switch (op_mode)
{
case QImode:
case HImode:
case SImode:
cmp_mode = SImode;
icode = (enum rtx_code) bit_code == AND ? CODE_FOR_ccmp_andsi
: CODE_FOR_ccmp_iorsi;
break;
case DImode:
cmp_mode = DImode;
icode = (enum rtx_code) bit_code == AND ? CODE_FOR_ccmp_anddi
: CODE_FOR_ccmp_iordi;
break;
default:
end_sequence ();
return NULL_RTX;
}
op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp);
op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp);
if (!op0 || !op1)
{
end_sequence ();
return NULL_RTX;
}
*prep_seq = get_insns ();
end_sequence ();
target = gen_rtx_REG (cc_mode, CC_REGNUM);
cmp1 = gen_rtx_fmt_ee ((enum rtx_code) cmp_code, cmp_mode, op0, op1);
cmp0 = gen_rtx_fmt_ee (NE, cmp_mode, prev, const0_rtx);
create_fixed_operand (&ops[0], prev);
create_fixed_operand (&ops[1], target);
create_fixed_operand (&ops[2], op0);
create_fixed_operand (&ops[3], op1);
create_fixed_operand (&ops[4], cmp0);
create_fixed_operand (&ops[5], cmp1);
push_to_sequence ((rtx_insn*) *gen_seq);
if (!maybe_expand_insn (icode, 6, ops))
{
end_sequence ();
return NULL_RTX;
}
*gen_seq = get_insns ();
end_sequence ();
return target;
}
#undef TARGET_GEN_CCMP_FIRST
#define TARGET_GEN_CCMP_FIRST aarch64_gen_ccmp_first
#undef TARGET_GEN_CCMP_NEXT
#define TARGET_GEN_CCMP_NEXT aarch64_gen_ccmp_next
/* Implement TARGET_SCHED_MACRO_FUSION_P. Return true if target supports /* Implement TARGET_SCHED_MACRO_FUSION_P. Return true if target supports
instruction fusion of some sort. */ instruction fusion of some sort. */
......
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
"" ""
"") "")
(define_insn "*ccmp_and" (define_insn "ccmp_and<mode>"
[(set (match_operand 1 "ccmp_cc_register" "") [(set (match_operand 1 "ccmp_cc_register" "")
(compare (compare
(and:SI (and:SI
...@@ -267,7 +267,7 @@ ...@@ -267,7 +267,7 @@
[(set_attr "type" "alus_sreg,alus_imm,alus_imm")] [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
) )
(define_insn "*ccmp_ior" (define_insn "ccmp_ior<mode>"
[(set (match_operand 1 "ccmp_cc_register" "") [(set (match_operand 1 "ccmp_cc_register" "")
(compare (compare
(ior:SI (ior:SI
...@@ -286,6 +286,20 @@ ...@@ -286,6 +286,20 @@
[(set_attr "type" "alus_sreg,alus_imm,alus_imm")] [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
) )
(define_expand "cmp<mode>"
[(set (match_operand 0 "cc_register" "")
(match_operator:CC 1 "aarch64_comparison_operator"
[(match_operand:GPI 2 "register_operand" "")
(match_operand:GPI 3 "aarch64_plus_operand" "")]))]
""
{
operands[1] = gen_rtx_fmt_ee (COMPARE,
SELECT_CC_MODE (GET_CODE (operands[1]),
operands[2], operands[3]),
operands[2], operands[3]);
}
)
(define_insn "*condjump" (define_insn "*condjump"
[(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
[(match_operand 1 "cc_register" "") (const_int 0)]) [(match_operand 1 "cc_register" "") (const_int 0)])
......
...@@ -11259,18 +11259,25 @@ This target hook is required only when the target has several different ...@@ -11259,18 +11259,25 @@ This target hook is required only when the target has several different
modes and they have different conditional execution capability, such as ARM. modes and they have different conditional execution capability, such as ARM.
@end deftypefn @end deftypefn
@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_FIRST (int @var{code}, rtx @var{op0}, rtx @var{op1}) @deftypefn {Target Hook} rtx TARGET_GEN_CCMP_FIRST (rtx *@var{prep_seq}, rtx *@var{gen_seq}, int @var{code}, tree @var{op0}, tree @var{op1})
This function emits a comparison insn for the first of a sequence of This function prepares to emit a comparison insn for the first compare in a
conditional comparisions. It returns a comparison expression appropriate sequence of conditional comparisions. It returns a appropriate @code{CC}
for passing to @code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is for passing to @code{gen_ccmp_next} or @code{cbranch_optab}. The insns to
prepare the compare are saved in @var{prep_seq} and the compare insns are
saved in @var{gen_seq}. They will be emitted when all the compares in the
the conditional comparision are generated without error. @var{code} is
the @code{rtx_code} of the compare for @var{op0} and @var{op1}. the @code{rtx_code} of the compare for @var{op0} and @var{op1}.
@end deftypefn @end deftypefn
@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_NEXT (rtx @var{prev}, int @var{cmp_code}, rtx @var{op0}, rtx @var{op1}, int @var{bit_code}) @deftypefn {Target Hook} rtx TARGET_GEN_CCMP_NEXT (rtx *@var{prep_seq}, rtx *@var{gen_seq}, rtx @var{prev}, int @var{cmp_code}, tree @var{op0}, tree @var{op1}, int @var{bit_code})
This function emits a conditional comparison within a sequence of This function prepare to emit a conditional comparison within a sequence of
conditional comparisons. The @var{prev} expression is the result of a conditional comparisons. It returns a appropriate @code{CC} for passing to
prior call to @code{gen_ccmp_first} or @code{gen_ccmp_next}. It may return @code{gen_ccmp_next} or @code{cbranch_optab}. The insns to prepare the
@code{NULL} if the combination of @var{prev} and this comparison is compare are saved in @var{prep_seq} and the compare insns are saved in
@var{gen_seq}. They will be emitted when all the compares in the conditional
comparision are generated without error. The @var{prev} expression is the
result of a prior call to @code{gen_ccmp_first} or @code{gen_ccmp_next}. It
may return @code{NULL} if the combination of @var{prev} and this comparison is
not supported, otherwise the result must be appropriate for passing to not supported, otherwise the result must be appropriate for passing to
@code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is the @code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is the
@code{rtx_code} of the compare for @var{op0} and @var{op1}. @var{bit_code} @code{rtx_code} of the compare for @var{op0} and @var{op1}. @var{bit_code}
......
...@@ -2542,24 +2542,31 @@ modes and they have different conditional execution capability, such as ARM.", ...@@ -2542,24 +2542,31 @@ modes and they have different conditional execution capability, such as ARM.",
DEFHOOK DEFHOOK
(gen_ccmp_first, (gen_ccmp_first,
"This function emits a comparison insn for the first of a sequence of\n\ "This function prepares to emit a comparison insn for the first compare in a\n\
conditional comparisions. It returns a comparison expression appropriate\n\ sequence of conditional comparisions. It returns a appropriate @code{CC}\n\
for passing to @code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is\n\ for passing to @code{gen_ccmp_next} or @code{cbranch_optab}. The insns to\n\
prepare the compare are saved in @var{prep_seq} and the compare insns are\n\
saved in @var{gen_seq}. They will be emitted when all the compares in the\n\
the conditional comparision are generated without error. @var{code} is\n\
the @code{rtx_code} of the compare for @var{op0} and @var{op1}.", the @code{rtx_code} of the compare for @var{op0} and @var{op1}.",
rtx, (int code, rtx op0, rtx op1), rtx, (rtx *prep_seq, rtx *gen_seq, int code, tree op0, tree op1),
NULL) NULL)
DEFHOOK DEFHOOK
(gen_ccmp_next, (gen_ccmp_next,
"This function emits a conditional comparison within a sequence of\n\ "This function prepare to emit a conditional comparison within a sequence of\n\
conditional comparisons. The @var{prev} expression is the result of a\n\ conditional comparisons. It returns a appropriate @code{CC} for passing to\n\
prior call to @code{gen_ccmp_first} or @code{gen_ccmp_next}. It may return\n\ @code{gen_ccmp_next} or @code{cbranch_optab}. The insns to prepare the\n\
@code{NULL} if the combination of @var{prev} and this comparison is\n\ compare are saved in @var{prep_seq} and the compare insns are saved in\n\
@var{gen_seq}. They will be emitted when all the compares in the conditional\n\
comparision are generated without error. The @var{prev} expression is the\n\
result of a prior call to @code{gen_ccmp_first} or @code{gen_ccmp_next}. It\n\
may return @code{NULL} if the combination of @var{prev} and this comparison is\n\
not supported, otherwise the result must be appropriate for passing to\n\ not supported, otherwise the result must be appropriate for passing to\n\
@code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is the\n\ @code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is the\n\
@code{rtx_code} of the compare for @var{op0} and @var{op1}. @var{bit_code}\n\ @code{rtx_code} of the compare for @var{op0} and @var{op1}. @var{bit_code}\n\
is @code{AND} or @code{IOR}, which is the op on the two compares.", is @code{AND} or @code{IOR}, which is the op on the two compares.",
rtx, (rtx prev, int cmp_code, rtx op0, rtx op1, int bit_code), rtx, (rtx *prep_seq, rtx *gen_seq, rtx prev, int cmp_code, tree op0, tree op1, int bit_code),
NULL) NULL)
/* Return a new value for loop unroll size. */ /* Return a new value for loop unroll size. */
......
2015-01-16 Zhenqiang Chen <zhenqiang.chen@arm.com>
* gcc.dg/pr64015.c: New test.
2015-01-16 Markus Trippelsdorf <markus@trippelsdorf.de> 2015-01-16 Markus Trippelsdorf <markus@trippelsdorf.de>
PR ipa/64163 PR ipa/64163
......
/* { dg-do compile } */
/* { dg-options "-O2 " } */
int
test (unsigned short a, unsigned char b)
{
return a > 0xfff2 && b > 252;
}
/* { dg-final { scan-assembler "ccmp" { target aarch64*-*-* } } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment