Commit f359611b by Uros Bizjak Committed by Uros Bizjak

i386-protos.h (ix86_split_fp_absneg_operator): New prototype.

	* config/i386/i386-protos.h (ix86_split_fp_absneg_operator):
	New prototype.
	* config/i386/i386-expand.c (ix86_expand_fp_absneg_operator):
	Emit clobber also for non-sse operations.
	(ix86_split_fp_absneg_operator): New function.
	* config/i386/i386.md (SSEMODEF): New mode iterator.
	(ssevecmodef): New mode attribute.
	(<code>tf2): Use absneg code iterator.
	(*<code>tf2_1): Rename from *absnegtf3_sse. Use absneg code iterator.
	Add three-operand AVX alternatives.
	(*<code><mode>2_i387_1): Rename from *absnegxf2_i387.
	Use absneg code iterator and X87MODEF mode iterator.
	(absneg fp_reg non-sse splitter): Call absneg code iterator
	and X87MODEF mode iterator.
	(absneg general_reg non-sse splitter): Use absneg code iterator
	and X87MODEF mode iterator.  Use ix86_split_fp_absneg_operator.
	(*<code><mode>2_1): Rename from *absneg<mode>2.  Use absneg
	code iterator.  Add three-operand AVX alternative.
	(absneg sse_reg splitter): Use absneg code iterator
	and SSEMODEF mode iterator.  Handle AVX operands.
	(absneg fp_reg splitter): Use absneg code iterator
	and MODEF mode iterator.
	(absneg general_reg splitter): Merge splitters using MODEF mode
	iterator.  Use absneg code iterator.  Call
	ix86_split_fp_absneg_operator.
	(*<code><mode>2_i387): Rename from *<code><mode>2_1.
	Do not enable for non-sse modes before reload.
	(CSGNMODE): Remove.
	(CSGNVMODE): Ditto.
	(copysing<mode>3): Use SSEMODEF instead of CSGNMODE and
	ssevecmodef mode attribute instaed of CSGNVMODE.
	(copysign<mode>3_const): Ditto.
	(copysign<mode>3_var): Ditto.
	* config/i386/i386.md (*<code><mode>2): Rename from *absneg<mode>2.
	Use absneg code iterator.  Simplify code using std::swap.
	* config/i386/predicates.md (absneg_operator): Remove.

From-SVN: r272123
parent f2ee751d
2019-06-10 Uroš Bizjak <ubizjak@gmail.com>
* config/i386/i386-protos.h (ix86_split_fp_absneg_operator):
New prototype.
* config/i386/i386-expand.c (ix86_expand_fp_absneg_operator):
Emit clobber also for non-sse operations.
(ix86_split_fp_absneg_operator): New function.
* config/i386/i386.md (SSEMODEF): New mode iterator.
(ssevecmodef): New mode attribute.
(<code>tf2): Use absneg code iterator.
(*<code>tf2_1): Rename from *absnegtf3_sse. Use absneg code iterator.
Add three-operand AVX alternatives.
(*<code><mode>2_i387_1): Rename from *absnegxf2_i387.
Use absneg code iterator and X87MODEF mode iterator.
(absneg fp_reg non-sse splitter): Call absneg code iterator
and X87MODEF mode iterator.
(absneg general_reg non-sse splitter): Use absneg code iterator
and X87MODEF mode iterator. Use ix86_split_fp_absneg_operator.
(*<code><mode>2_1): Rename from *absneg<mode>2. Use absneg
code iterator. Add three-operand AVX alternative.
(absneg sse_reg splitter): Use absneg code iterator
and SSEMODEF mode iterator. Handle AVX operands.
(absneg fp_reg splitter): Use absneg code iterator
and MODEF mode iterator.
(absneg general_reg splitter): Merge splitters using MODEF mode
iterator. Use absneg code iterator. Call
ix86_split_fp_absneg_operator.
(*<code><mode>2_i387): Rename from *<code><mode>2_1.
Do not enable for non-sse modes before reload.
(CSGNMODE): Remove.
(CSGNVMODE): Ditto.
(copysing<mode>3): Use SSEMODEF instead of CSGNMODE and
ssevecmodef mode attribute instaed of CSGNVMODE.
(copysign<mode>3_const): Ditto.
(copysign<mode>3_var): Ditto.
* config/i386/i386.md (*<code><mode>2): Rename from *absneg<mode>2.
Use absneg code iterator. Simplify code using std::swap.
* config/i386/predicates.md (absneg_operator): Remove.
2019-06-10 Martin Sebor <msebor@redhat.com> 2019-06-10 Martin Sebor <msebor@redhat.com>
* gimple-fold.c (get_range_strlen): Update comment that didn't * gimple-fold.c (get_range_strlen): Update comment that didn't
......
...@@ -1704,10 +1704,11 @@ void ...@@ -1704,10 +1704,11 @@ void
ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode, ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
rtx operands[]) rtx operands[])
{ {
rtx mask, set, dst, src; rtx set, dst, src;
bool use_sse = false; bool use_sse = false;
bool vector_mode = VECTOR_MODE_P (mode); bool vector_mode = VECTOR_MODE_P (mode);
machine_mode vmode = mode; machine_mode vmode = mode;
rtvec par;
if (vector_mode) if (vector_mode)
use_sse = true; use_sse = true;
...@@ -1722,24 +1723,19 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode, ...@@ -1722,24 +1723,19 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
vmode = V2DFmode; vmode = V2DFmode;
} }
/* NEG and ABS performed with SSE use bitwise mask operations.
Create the appropriate mask now. */
if (use_sse)
mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
else
mask = NULL_RTX;
dst = operands[0]; dst = operands[0];
src = operands[1]; src = operands[1];
set = gen_rtx_fmt_e (code, mode, src); set = gen_rtx_fmt_e (code, mode, src);
set = gen_rtx_SET (dst, set); set = gen_rtx_SET (dst, set);
if (mask) if (use_sse)
{ {
rtx use, clob; rtx mask, use, clob;
rtvec par;
/* NEG and ABS performed with SSE use bitwise mask operations.
Create the appropriate mask now. */
mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
use = gen_rtx_USE (VOIDmode, mask); use = gen_rtx_USE (VOIDmode, mask);
if (vector_mode) if (vector_mode)
par = gen_rtvec (2, set, use); par = gen_rtvec (2, set, use);
...@@ -1748,10 +1744,104 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode, ...@@ -1748,10 +1744,104 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
par = gen_rtvec (3, set, use, clob); par = gen_rtvec (3, set, use, clob);
} }
emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
} }
else else
emit_insn (set); {
rtx clob;
/* Changing of sign for FP values is doable using integer unit too. */
clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
par = gen_rtvec (2, set, clob);
}
emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
}
/* Deconstruct a floating point ABS or NEG operation
with integer registers into integer operations. */
void
ix86_split_fp_absneg_operator (enum rtx_code code, machine_mode mode,
rtx operands[])
{
enum rtx_code absneg_op;
rtx dst, set;
gcc_assert (operands_match_p (operands[0], operands[1]));
switch (mode)
{
case E_SFmode:
dst = gen_lowpart (SImode, operands[0]);
if (code == ABS)
{
set = gen_int_mode (0x7fffffff, SImode);
absneg_op = AND;
}
else
{
set = gen_int_mode (0x80000000, SImode);
absneg_op = XOR;
}
set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
break;
case E_DFmode:
if (TARGET_64BIT)
{
dst = gen_lowpart (DImode, operands[0]);
dst = gen_rtx_ZERO_EXTRACT (DImode, dst, const1_rtx, GEN_INT (63));
if (code == ABS)
set = const0_rtx;
else
set = gen_rtx_NOT (DImode, dst);
}
else
{
dst = gen_highpart (SImode, operands[0]);
if (code == ABS)
{
set = gen_int_mode (0x7fffffff, SImode);
absneg_op = AND;
}
else
{
set = gen_int_mode (0x80000000, SImode);
absneg_op = XOR;
}
set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
}
break;
case E_XFmode:
dst = gen_rtx_REG (SImode,
REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2));
if (code == ABS)
{
set = GEN_INT (0x7fff);
absneg_op = AND;
}
else
{
set = GEN_INT (0x8000);
absneg_op = XOR;
}
set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
break;
default:
gcc_unreachable ();
}
set = gen_rtx_SET (dst, set);
rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
rtvec par = gen_rtvec (2, set, clob);
emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
} }
/* Expand a copysign operation. Special case operand 0 being a constant. */ /* Expand a copysign operation. Special case operand 0 being a constant. */
......
...@@ -121,6 +121,8 @@ extern rtx ix86_expand_adjust_ufix_to_sfix_si (rtx, rtx *); ...@@ -121,6 +121,8 @@ extern rtx ix86_expand_adjust_ufix_to_sfix_si (rtx, rtx *);
extern enum ix86_fpcmp_strategy ix86_fp_comparison_strategy (enum rtx_code); extern enum ix86_fpcmp_strategy ix86_fp_comparison_strategy (enum rtx_code);
extern void ix86_expand_fp_absneg_operator (enum rtx_code, machine_mode, extern void ix86_expand_fp_absneg_operator (enum rtx_code, machine_mode,
rtx[]); rtx[]);
extern void ix86_split_fp_absneg_operator (enum rtx_code, machine_mode,
rtx[]);
extern void ix86_expand_copysign (rtx []); extern void ix86_expand_copysign (rtx []);
extern void ix86_split_copysign_const (rtx []); extern void ix86_split_copysign_const (rtx []);
extern void ix86_split_copysign_var (rtx []); extern void ix86_split_copysign_var (rtx []);
......
...@@ -1404,9 +1404,6 @@ ...@@ -1404,9 +1404,6 @@
(define_predicate "compare_operator" (define_predicate "compare_operator"
(match_code "compare")) (match_code "compare"))
(define_predicate "absneg_operator"
(match_code "abs,neg"))
;; Return true if OP is a memory operand, aligned to ;; Return true if OP is a memory operand, aligned to
;; less than its natural alignment. ;; less than its natural alignment.
(define_predicate "misaligned_operand" (define_predicate "misaligned_operand"
......
...@@ -1720,41 +1720,31 @@ ...@@ -1720,41 +1720,31 @@
"TARGET_SSE" "TARGET_SSE"
"ix86_expand_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;") "ix86_expand_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
(define_insn_and_split "*absneg<mode>2" (define_insn_and_split "*<code><mode>2"
[(set (match_operand:VF 0 "register_operand" "=x,x,v,v") [(set (match_operand:VF 0 "register_operand" "=x,x,v,v")
(match_operator:VF 3 "absneg_operator" (absneg:VF
[(match_operand:VF 1 "vector_operand" "0, xBm,v, m")])) (match_operand:VF 1 "vector_operand" "0, xBm,v, m")))
(use (match_operand:VF 2 "vector_operand" "xBm,0, vm,v"))] (use (match_operand:VF 2 "vector_operand" "xBm,0, vm,v"))]
"TARGET_SSE" "TARGET_SSE"
"#" "#"
"&& reload_completed" "&& reload_completed"
[(const_int 0)] [(set (match_dup 0) (match_dup 3))]
{ {
enum rtx_code absneg_op; enum rtx_code absneg_op = <CODE> == ABS ? AND : XOR;
rtx op1, op2;
rtx t;
if (TARGET_AVX) if (TARGET_AVX)
{ {
if (MEM_P (operands[1])) if (MEM_P (operands[1]))
op1 = operands[2], op2 = operands[1]; std::swap (operands[1], operands[2]);
else
op1 = operands[1], op2 = operands[2];
} }
else else
{ {
op1 = operands[0]; if (operands_match_p (operands[0], operands[2]))
if (rtx_equal_p (operands[0], operands[1])) std::swap (operands[1], operands[2]);
op2 = operands[2]; }
else
op2 = operands[1];
}
absneg_op = GET_CODE (operands[3]) == NEG ? XOR : AND; operands[3]
t = gen_rtx_fmt_ee (absneg_op, <MODE>mode, op1, op2); = gen_rtx_fmt_ee (absneg_op, <MODE>mode, operands[1], operands[2]);
t = gen_rtx_SET (operands[0], t);
emit_insn (t);
DONE;
} }
[(set_attr "isa" "noavx,noavx,avx,avx")]) [(set_attr "isa" "noavx,noavx,avx,avx")])
......
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