aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/config/i386/i386-protos.h4
-rw-r--r--gcc/config/i386/i386.c90
-rw-r--r--gcc/config/i386/i386.md104
4 files changed, 178 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac4c2b1..ba3e1fb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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,
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index fcbb822..feacd2d 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -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 *);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8508cd8..4b6b3f2 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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);
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 21134d6..4f8d310 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -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"
+(define_insn_and_split "copysignsf3_const"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (unspec:SF
+ [(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_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:V4SF 3 "nonimmediate_operand" " X,xm,xm, 0,0")
- (match_operand:SF 4 "register_operand" " 1, 1, x, 1,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"
- "#"
- "&& reload_completed"
+ "#")
+
+(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 (operands);
+ 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"
+(define_insn_and_split "copysigndf3_const"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (unspec:DF
+ [(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_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:V2DF 3 "nonimmediate_operand" " X,xm,xm, 0,0")
- (match_operand:DF 4 "register_operand" " 1, 1, x, 1,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"
- "#"
- "&& reload_completed"
+ "#")
+
+(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 (operands);
+ ix86_split_copysign_var (operands);
DONE;
})