diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 90 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 104 |
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; }) |