[optabs][ifcvt][1/3] Define negcc, notcc optabs

* ifcvt.c (noce_try_inverse_constants): New function.
	(noce_process_if_block): Call it.
	* optabs.h (emit_conditional_neg_or_complement): Declare prototype.
	* optabs.def (negcc_optab, notcc_optab): Declare.
	* optabs.c (emit_conditional_neg_or_complement): New function.
	* doc/tm.texi (Standard Names): Document negcc, notcc names.

From-SVN: r230089
This commit is contained in:
Kyrylo Tkachov 2015-11-10 09:35:11 +00:00 committed by Kyrylo Tkachov
parent df554b0e49
commit ce68b5cfb9
6 changed files with 159 additions and 0 deletions

View File

@ -1,3 +1,12 @@
2015-11-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* ifcvt.c (noce_try_inverse_constants): New function.
(noce_process_if_block): Call it.
* optabs.h (emit_conditional_neg_or_complement): Declare prototype.
* optabs.def (negcc_optab, notcc_optab): Declare.
* optabs.c (emit_conditional_neg_or_complement): New function.
* doc/tm.texi (Standard Names): Document negcc, notcc names.
2015-11-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR rtl-optimization/68236

View File

@ -5805,6 +5805,21 @@ move operand 2 or (operands 2 + operand 3) into operand 0 according to the
comparison in operand 1. If the comparison is false, operand 2 is moved into
operand 0, otherwise (operand 2 + operand 3) is moved.
@cindex @code{neg@var{mode}cc} instruction pattern
@item @samp{neg@var{mode}cc}
Similar to @samp{mov@var{mode}cc} but for conditional negation. Conditionally
move the negation of operand 2 or the unchanged operand 3 into operand 0
according to the comparison in operand 1. If the comparison is true, the negation
of operand 2 is moved into operand 0, otherwise operand 3 is moved.
@cindex @code{not@var{mode}cc} instruction pattern
@item @samp{not@var{mode}cc}
Similar to @samp{neg@var{mode}cc} but for conditional complement.
Conditionally move the bitwise complement of operand 2 or the unchanged
operand 3 into operand 0 according to the comparison in operand 1.
If the comparison is true, the complement of operand 2 is moved into
operand 0, otherwise operand 3 is moved.
@cindex @code{cstore@var{mode}4} instruction pattern
@item @samp{cstore@var{mode}4}
Store zero or nonzero in operand 0 according to whether a comparison

View File

@ -1168,6 +1168,83 @@ noce_try_store_flag (struct noce_if_info *if_info)
}
}
/* Convert "if (test) x = -A; else x = A" into
x = A; if (test) x = -x if the machine can do the
conditional negate form of this cheaply.
Try this before noce_try_cmove that will just load the
immediates into two registers and do a conditional select
between them. If the target has a conditional negate or
conditional invert operation we can save a potentially
expensive constant synthesis. */
static bool
noce_try_inverse_constants (struct noce_if_info *if_info)
{
if (!noce_simple_bbs (if_info))
return false;
if (!CONST_INT_P (if_info->a)
|| !CONST_INT_P (if_info->b)
|| !REG_P (if_info->x))
return false;
machine_mode mode = GET_MODE (if_info->x);
HOST_WIDE_INT val_a = INTVAL (if_info->a);
HOST_WIDE_INT val_b = INTVAL (if_info->b);
rtx cond = if_info->cond;
rtx x = if_info->x;
rtx target;
start_sequence ();
rtx_code code;
if (val_b != HOST_WIDE_INT_MIN && val_a == -val_b)
code = NEG;
else if (val_a == ~val_b)
code = NOT;
else
{
end_sequence ();
return false;
}
rtx tmp = gen_reg_rtx (mode);
noce_emit_move_insn (tmp, if_info->a);
target = emit_conditional_neg_or_complement (x, code, mode, cond, tmp, tmp);
if (target)
{
rtx_insn *seq = get_insns ();
if (!seq)
{
end_sequence ();
return false;
}
if (target != if_info->x)
noce_emit_move_insn (if_info->x, target);
seq = end_ifcvt_sequence (if_info);
if (!seq)
return false;
emit_insn_before_setloc (seq, if_info->jump,
INSN_LOCATION (if_info->insn_a));
return true;
}
end_sequence ();
return false;
}
/* Convert "if (test) x = a; else x = b", for A and B constant.
Also allow A = y + c1, B = y + c2, with a common y between A
and B. */
@ -3497,6 +3574,8 @@ noce_process_if_block (struct noce_if_info *if_info)
goto success;
if (noce_try_abs (if_info))
goto success;
if (noce_try_inverse_constants (if_info))
goto success;
if (!targetm.have_conditional_execution ()
&& noce_try_store_flag_constants (if_info))
goto success;

View File

@ -4210,6 +4210,56 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
return NULL_RTX;
}
/* Emit a conditional negate or bitwise complement using the
negcc or notcc optabs if available. Return NULL_RTX if such operations
are not available. Otherwise return the RTX holding the result.
TARGET is the desired destination of the result. COMP is the comparison
on which to negate. If COND is true move into TARGET the negation
or bitwise complement of OP1. Otherwise move OP2 into TARGET.
CODE is either NEG or NOT. MODE is the machine mode in which the
operation is performed. */
rtx
emit_conditional_neg_or_complement (rtx target, rtx_code code,
machine_mode mode, rtx cond, rtx op1,
rtx op2)
{
optab op = unknown_optab;
if (code == NEG)
op = negcc_optab;
else if (code == NOT)
op = notcc_optab;
else
gcc_unreachable ();
insn_code icode = direct_optab_handler (op, mode);
if (icode == CODE_FOR_nothing)
return NULL_RTX;
if (!target)
target = gen_reg_rtx (mode);
rtx_insn *last = get_last_insn ();
struct expand_operand ops[4];
create_output_operand (&ops[0], target, mode);
create_fixed_operand (&ops[1], cond);
create_input_operand (&ops[2], op1, mode);
create_input_operand (&ops[3], op2, mode);
if (maybe_expand_insn (icode, 4, ops))
{
if (ops[0].value != target)
convert_move (target, ops[0].value, false);
return target;
}
delete_insns_since (last);
return NULL_RTX;
}
/* Emit a conditional addition instruction if the machine supports one for that
condition and machine mode.

View File

@ -183,6 +183,8 @@ OPTAB_D (reload_out_optab, "reload_out$a")
OPTAB_DC(cbranch_optab, "cbranch$a4", COMPARE)
OPTAB_D (addcc_optab, "add$acc")
OPTAB_D (negcc_optab, "neg$acc")
OPTAB_D (notcc_optab, "not$acc")
OPTAB_D (movcc_optab, "mov$acc")
OPTAB_D (cmov_optab, "cmov$a6")
OPTAB_D (cstore_optab, "cstore$a4")

View File

@ -259,6 +259,10 @@ extern void emit_indirect_jump (rtx);
rtx emit_conditional_move (rtx, enum rtx_code, rtx, rtx, machine_mode,
rtx, rtx, machine_mode, int);
/* Emit a conditional negate or bitwise complement operation. */
rtx emit_conditional_neg_or_complement (rtx, rtx_code, machine_mode, rtx,
rtx, rtx);
rtx emit_conditional_add (rtx, enum rtx_code, rtx, rtx, machine_mode,
rtx, rtx, machine_mode, int);