re PR target/19700 (ICE in final_scan_insn with O1 -g -march=athlon-xp -mfpmath=sse)

PR target/19700
        * config/i386/i386.c (ix86_expand_copysign): New.
        (ix86_split_copysign_const): New.
        (ix86_split_copysign_var): Rename from ix86_split_copysign,
        rearrange op1/nmask operands.
        * config/i386/i386-protos.h: Update.
        * config/i386/i386.md (copysignsf3): Use ix86_expand_copysign.
        (copysigndf3): Likewise.
        (copysignsf3_const, copysigndf3_const): New.
        (copysignsf3_var): Rename from copysignsf3, split out splitter
        and fix split predicate for X constraint.
        (copysigndf3_var): Similarly.

From-SVN: r94442
This commit is contained in:
Richard Henderson 2005-01-30 09:48:01 -08:00 committed by Richard Henderson
parent c5c367ac3d
commit b99d6d2b80
4 changed files with 184 additions and 41 deletions

View File

@ -1,3 +1,18 @@
2005-01-30 Richard Henderson <rth@redhat.com>
PR target/19700
* config/i386/i386.c (ix86_expand_copysign): New.
(ix86_split_copysign_const): New.
(ix86_split_copysign_var): Rename from ix86_split_copysign,
rearrange op1/nmask operands.
* config/i386/i386-protos.h: Update.
* config/i386/i386.md (copysignsf3): Use ix86_expand_copysign.
(copysigndf3): Likewise.
(copysignsf3_const, copysigndf3_const): New.
(copysignsf3_var): Rename from copysignsf3, split out splitter
and fix split predicate for X constraint.
(copysigndf3_var): Similarly.
2005-01-30 Kazu Hirata <kazu@cs.umass.edu>
* optabs.c, doc/c-tree.texi, doc/install.texi, doc/md.texi,

View File

@ -139,7 +139,9 @@ extern void ix86_expand_unary_operator (enum rtx_code, enum machine_mode,
extern rtx ix86_build_signbit_mask (enum machine_mode, bool, bool);
extern void ix86_expand_fp_absneg_operator (enum rtx_code, enum machine_mode,
rtx[]);
extern void ix86_split_copysign (rtx []);
extern void ix86_expand_copysign (rtx []);
extern void ix86_split_copysign_const (rtx []);
extern void ix86_split_copysign_var (rtx []);
extern int ix86_unary_operator_ok (enum rtx_code, enum machine_mode, rtx[]);
extern int ix86_match_ccmode (rtx, enum machine_mode);
extern rtx ix86_expand_compare (enum rtx_code, rtx *, rtx *);

View File

@ -8117,10 +8117,92 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, enum machine_mode mode,
emit_move_insn (operands[0], dst);
}
/* Deconstruct a copysign operation into bit masks. */
/* Expand a copysign operation. Special case operand 0 being a constant. */
void
ix86_split_copysign (rtx operands[])
ix86_expand_copysign (rtx operands[])
{
enum machine_mode mode, vmode;
rtx dest, op0, op1, mask, nmask;
dest = operands[0];
op0 = operands[1];
op1 = operands[2];
mode = GET_MODE (dest);
vmode = mode == SFmode ? V4SFmode : V2DFmode;
if (GET_CODE (op0) == CONST_DOUBLE)
{
rtvec v;
if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
op0 = simplify_unary_operation (ABS, mode, op0, mode);
if (op0 == CONST0_RTX (mode))
op0 = CONST0_RTX (vmode);
else
{
if (mode == SFmode)
v = gen_rtvec (4, op0, CONST0_RTX (SFmode),
CONST0_RTX (SFmode), CONST0_RTX (SFmode));
else
v = gen_rtvec (2, op0, CONST0_RTX (DFmode));
op0 = force_reg (vmode, gen_rtx_CONST_VECTOR (vmode, v));
}
mask = ix86_build_signbit_mask (mode, 0, 0);
if (mode == SFmode)
emit_insn (gen_copysignsf3_const (dest, op0, op1, mask));
else
emit_insn (gen_copysigndf3_const (dest, op0, op1, mask));
}
else
{
nmask = ix86_build_signbit_mask (mode, 0, 1);
mask = ix86_build_signbit_mask (mode, 0, 0);
if (mode == SFmode)
emit_insn (gen_copysignsf3_var (dest, NULL, op0, op1, nmask, mask));
else
emit_insn (gen_copysigndf3_var (dest, NULL, op0, op1, nmask, mask));
}
}
/* Deconstruct a copysign operation into bit masks. Operand 0 is known to
be a constant, and so has already been expanded into a vector constant. */
void
ix86_split_copysign_const (rtx operands[])
{
enum machine_mode mode, vmode;
rtx dest, op0, op1, mask, x;
dest = operands[0];
op0 = operands[1];
op1 = operands[2];
mask = operands[3];
mode = GET_MODE (dest);
vmode = GET_MODE (mask);
dest = simplify_gen_subreg (vmode, dest, mode, 0);
x = gen_rtx_AND (vmode, dest, mask);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
if (op0 != CONST0_RTX (vmode))
{
x = gen_rtx_IOR (vmode, dest, op0);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
}
}
/* Deconstruct a copysign operation into bit masks. Operand 0 is variable,
so we have to do two masks. */
void
ix86_split_copysign_var (rtx operands[])
{
enum machine_mode mode, vmode;
rtx dest, scratch, op0, op1, mask, nmask, x;
@ -8128,8 +8210,8 @@ ix86_split_copysign (rtx operands[])
dest = operands[0];
scratch = operands[1];
op0 = operands[2];
nmask = operands[3];
op1 = operands[4];
op1 = operands[3];
nmask = operands[4];
mask = operands[5];
mode = GET_MODE (dest);

View File

@ -9452,34 +9452,56 @@
"#")
(define_expand "copysignsf3"
[(parallel [(set (match_operand:SF 0 "register_operand" "")
(unspec:SF [(match_operand:SF 1 "register_operand" "")
(match_dup 4)
(match_operand:SF 2 "register_operand" "")
(match_dup 5)]
UNSPEC_COPYSIGN))
(clobber (match_scratch:V4SF 3 ""))])]
[(match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "nonmemory_operand" "")
(match_operand:SF 2 "register_operand" "")]
"TARGET_SSE_MATH"
{
operands[4] = ix86_build_signbit_mask (SFmode, 0, 1);
operands[5] = ix86_build_signbit_mask (SFmode, 0, 0);
ix86_expand_copysign (operands);
DONE;
})
(define_insn_and_split "*copysignsf3"
[(set (match_operand:SF 0 "register_operand" "=x, x, x, x,x")
(define_insn_and_split "copysignsf3_const"
[(set (match_operand:SF 0 "register_operand" "=x")
(unspec:SF
[(match_operand:SF 2 "register_operand" " x, 0, 0, x,x")
(match_operand:V4SF 3 "nonimmediate_operand" " X,xm,xm, 0,0")
(match_operand:SF 4 "register_operand" " 1, 1, x, 1,x")
(match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
UNSPEC_COPYSIGN))
(clobber (match_scratch:V4SF 1 "=x, x, x, x,x"))]
[(match_operand:V4SF 1 "vector_move_operand" "xmC")
(match_operand:SF 2 "register_operand" "0")
(match_operand:V4SF 3 "nonimmediate_operand" "xm")]
UNSPEC_COPYSIGN))]
"TARGET_SSE_MATH"
"#"
"&& reload_completed"
[(const_int 0)]
{
ix86_split_copysign (operands);
ix86_split_copysign_const (operands);
DONE;
})
(define_insn "copysignsf3_var"
[(set (match_operand:SF 0 "register_operand" "=x, x, x, x,x")
(unspec:SF
[(match_operand:SF 2 "register_operand" " x, 0, 0, x,x")
(match_operand:SF 3 "register_operand" " 1, 1, x, 1,x")
(match_operand:V4SF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
(match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
UNSPEC_COPYSIGN))
(clobber (match_scratch:V4SF 1 "=x, x, x, x,x"))]
"TARGET_SSE_MATH"
"#")
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(unspec:SF
[(match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "register_operand" "")
(match_operand:V4SF 4 "" "")
(match_operand:V4SF 5 "" "")]
UNSPEC_COPYSIGN))
(clobber (match_scratch:V4SF 1 ""))]
"TARGET_SSE_MATH && reload_completed"
[(const_int 0)]
{
ix86_split_copysign_var (operands);
DONE;
})
@ -9526,34 +9548,56 @@
"#")
(define_expand "copysigndf3"
[(parallel [(set (match_operand:DF 0 "register_operand" "")
(unspec:DF [(match_operand:DF 1 "register_operand" "")
(match_dup 4)
(match_operand:DF 2 "register_operand" "")
(match_dup 5)]
UNSPEC_COPYSIGN))
(clobber (match_scratch:V2DF 3 ""))])]
[(match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "nonmemory_operand" "")
(match_operand:DF 2 "register_operand" "")]
"TARGET_SSE2 && TARGET_SSE_MATH"
{
operands[4] = ix86_build_signbit_mask (DFmode, 0, 1);
operands[5] = ix86_build_signbit_mask (DFmode, 0, 0);
ix86_expand_copysign (operands);
DONE;
})
(define_insn_and_split "*copysigndf3"
[(set (match_operand:DF 0 "register_operand" "=x, x, x, x,x")
(define_insn_and_split "copysigndf3_const"
[(set (match_operand:DF 0 "register_operand" "=x")
(unspec:DF
[(match_operand:DF 2 "register_operand" " x, 0, 0, x,x")
(match_operand:V2DF 3 "nonimmediate_operand" " X,xm,xm, 0,0")
(match_operand:DF 4 "register_operand" " 1, 1, x, 1,x")
(match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
UNSPEC_COPYSIGN))
(clobber (match_scratch:V2DF 1 "=x, x, x, x,x"))]
[(match_operand:V2DF 1 "vector_move_operand" "xmC")
(match_operand:DF 2 "register_operand" "0")
(match_operand:V2DF 3 "nonimmediate_operand" "xm")]
UNSPEC_COPYSIGN))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"#"
"&& reload_completed"
[(const_int 0)]
{
ix86_split_copysign (operands);
ix86_split_copysign_const (operands);
DONE;
})
(define_insn "copysigndf3_var"
[(set (match_operand:DF 0 "register_operand" "=x, x, x, x,x")
(unspec:DF
[(match_operand:DF 2 "register_operand" " x, 0, 0, x,x")
(match_operand:DF 3 "register_operand" " 1, 1, x, 1,x")
(match_operand:V2DF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
(match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
UNSPEC_COPYSIGN))
(clobber (match_scratch:V2DF 1 "=x, x, x, x,x"))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"#")
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(unspec:DF
[(match_operand:DF 2 "register_operand" "")
(match_operand:DF 3 "register_operand" "")
(match_operand:V2DF 4 "" "")
(match_operand:V2DF 5 "" "")]
UNSPEC_COPYSIGN))
(clobber (match_scratch:V2DF 1 ""))]
"TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
[(const_int 0)]
{
ix86_split_copysign_var (operands);
DONE;
})