Commit ab8efbd8 by Richard Henderson Committed by Richard Henderson

i386.c (ix86_prepare_sse_fp_compare_args): Split ...

        * config/i386/i386.c (ix86_prepare_sse_fp_compare_args): Split ...
        (ix86_expand_sse_fp_minmax): ... from ...
        (ix86_expand_fp_movcc): ... here.
        (ix86_expand_sse_movcc): Rewrite from ix86_split_sse_movcc.
        * config/i386/i386-protos.h: Update.
        * config/i386/i386.md (UNSPEC_IEEE_MIN, UNSPEC_IEEE_MAX): New.
        (sse_setccsf, sse_setccdf): Allow before reload.
        (movsfcc_1_sse_min, movsfcc_1_sse_max, movsfcc_1_sse): Remove.
        (movdfcc_1_sse_min, movdfcc_1_sse_max, movdfcc_1_sse): Remove.
        (ieee_sminsf3, ieee_smaxsf3, ieee_smindf3, ieee_smaxdf3): New.
        * config/i386/sse.md (andsf3, nandsf3, iorsf3, xorsf3): New.
        (anddf3, nanddf3, iordf3, xordf3): New.

From-SVN: r98068
parent 0b90f180
2005-04-12 Richard Henderson <rth@redhat.com>
* config/i386/i386.c (ix86_prepare_sse_fp_compare_args): Split ...
(ix86_expand_sse_fp_minmax): ... from ...
(ix86_expand_fp_movcc): ... here.
(ix86_expand_sse_movcc): Rewrite from ix86_split_sse_movcc.
* config/i386/i386-protos.h: Update.
* config/i386/i386.md (UNSPEC_IEEE_MIN, UNSPEC_IEEE_MAX): New.
(sse_setccsf, sse_setccdf): Allow before reload.
(movsfcc_1_sse_min, movsfcc_1_sse_max, movsfcc_1_sse): Remove.
(movdfcc_1_sse_min, movdfcc_1_sse_max, movdfcc_1_sse): Remove.
(ieee_sminsf3, ieee_smaxsf3, ieee_smindf3, ieee_smaxdf3): New.
* config/i386/sse.md (andsf3, nandsf3, iorsf3, xorsf3): New.
(anddf3, nanddf3, iordf3, xordf3): New.
2005-04-12 Jeff Law <law@redhat.com>
* Makefile.in (OBJS-common): Add tree-ssa-uncprop.o.
......
......@@ -150,7 +150,6 @@ extern void ix86_expand_branch (enum rtx_code, rtx);
extern int ix86_expand_setcc (enum rtx_code, rtx);
extern int ix86_expand_int_movcc (rtx[]);
extern int ix86_expand_fp_movcc (rtx[]);
extern void ix86_split_sse_movcc (rtx[]);
extern int ix86_expand_int_addcc (rtx[]);
extern void ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int);
extern void x86_initialize_trampoline (rtx, rtx, rtx);
......
......@@ -104,6 +104,8 @@
; Generic math support
(UNSPEC_COPYSIGN 50)
(UNSPEC_IEEE_MIN 51) ; not commutative
(UNSPEC_IEEE_MAX 52) ; not commutative
; x87 Floating point
(UNSPEC_SIN 60)
......@@ -12462,17 +12464,14 @@
;; The SSE store flag instructions saves 0 or 0xffffffff to the result.
;; subsequent logical operations are used to imitate conditional moves.
;; 0xffffffff is NaN, but not in normalized form, so we can't represent
;; it directly. Further holding this value in pseudo register might bring
;; problem in implicit normalization in spill code.
;; So we don't define FLOAT_STORE_FLAG_VALUE and create these
;; instructions after reload by splitting the conditional move patterns.
;; it directly.
(define_insn "*sse_setccsf"
[(set (match_operand:SF 0 "register_operand" "=x")
(match_operator:SF 1 "sse_comparison_operator"
[(match_operand:SF 2 "register_operand" "0")
(match_operand:SF 3 "nonimmediate_operand" "xm")]))]
"TARGET_SSE && reload_completed"
"TARGET_SSE"
"cmp%D1ss\t{%3, %0|%0, %3}"
[(set_attr "type" "ssecmp")
(set_attr "mode" "SF")])
......@@ -12482,7 +12481,7 @@
(match_operator:DF 1 "sse_comparison_operator"
[(match_operand:DF 2 "register_operand" "0")
(match_operand:DF 3 "nonimmediate_operand" "Ym")]))]
"TARGET_SSE2 && reload_completed"
"TARGET_SSE2"
"cmp%D1sd\t{%3, %0|%0, %3}"
[(set_attr "type" "ssecmp")
(set_attr "mode" "DF")])
......@@ -17707,51 +17706,6 @@
"(TARGET_80387 && TARGET_CMOVE) || TARGET_SSE_MATH"
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
;; These versions of min/max are aware of the instruction's behavior
;; wrt -0.0 and NaN inputs. If we don't care about either, then we
;; should have used the smin/smax expanders in the first place.
(define_insn "*movsfcc_1_sse_min"
[(set (match_operand:SF 0 "register_operand" "=x")
(if_then_else:SF
(lt:SF (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonimmediate_operand" "xm"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE_MATH"
"minss\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "SF")])
(define_insn "*movsfcc_1_sse_max"
[(set (match_operand:SF 0 "register_operand" "=x")
(if_then_else:SF
(lt:SF (match_operand:SF 2 "nonimmediate_operand" "xm")
(match_operand:SF 1 "nonimmediate_operand" "0"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE_MATH"
"maxss\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "SF")])
(define_insn_and_split "*movsfcc_1_sse"
[(set (match_operand:SF 0 "register_operand" "=x,x,x")
(if_then_else:SF
(match_operator:SF 4 "sse_comparison_operator"
[(match_operand:SF 5 "register_operand" "0,0,0")
(match_operand:SF 6 "nonimmediate_operand" "xm,xm,xm")])
(match_operand:SF 2 "reg_or_0_operand" "C,x,x")
(match_operand:SF 3 "reg_or_0_operand" "x,C,x")))
(clobber (match_scratch:V4SF 1 "=&x,&x,&x"))]
"TARGET_SSE_MATH"
"#"
"&& reload_completed"
[(const_int 0)]
{
ix86_split_sse_movcc (operands);
DONE;
})
(define_insn "*movsfcc_1_387"
[(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f")
(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
......@@ -17776,51 +17730,6 @@
"(TARGET_80387 && TARGET_CMOVE) || (TARGET_SSE2 && TARGET_SSE_MATH)"
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
;; These versions of min/max are aware of the instruction's behavior
;; wrt -0.0 and NaN inputs. If we don't care about either, then we
;; should have used the smin/smax expanders in the first place.
(define_insn "*movdfcc_1_sse_min"
[(set (match_operand:DF 0 "register_operand" "=x")
(if_then_else:DF
(lt:DF (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "nonimmediate_operand" "xm"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"minsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "DF")])
(define_insn "*movdfcc_1_sse_max"
[(set (match_operand:DF 0 "register_operand" "=x")
(if_then_else:DF
(lt:DF (match_operand:DF 2 "nonimmediate_operand" "xm")
(match_operand:DF 1 "nonimmediate_operand" "0"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"maxsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "DF")])
(define_insn_and_split "*movdfcc_1_sse"
[(set (match_operand:DF 0 "register_operand" "=x,x,x")
(if_then_else:DF
(match_operator:DF 4 "sse_comparison_operator"
[(match_operand:DF 5 "register_operand" "0,0,0")
(match_operand:DF 6 "nonimmediate_operand" "xm,xm,xm")])
(match_operand:DF 2 "reg_or_0_operand" "C,x,x")
(match_operand:DF 3 "reg_or_0_operand" "x,C,x")))
(clobber (match_scratch:V2DF 1 "=&x,&x,&x"))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"#"
"&& reload_completed"
[(const_int 0)]
{
ix86_split_sse_movcc (operands);
DONE;
})
(define_insn "*movdfcc_1"
[(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
......@@ -17935,6 +17844,52 @@
[(set_attr "type" "sseadd")
(set_attr "mode" "DF")])
;; These versions of the min/max patterns implement exactly the operations
;; min = (op1 < op2 ? op1 : op2)
;; max = (!(op1 < op2) ? op1 : op2)
;; Their operands are not commutative, and thus they may be used in the
;; presence of -0.0 and NaN.
(define_insn "*ieee_sminsf3"
[(set (match_operand:SF 0 "register_operand" "=x")
(unspec:SF [(match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonimmediate_operand" "xm")]
UNSPEC_IEEE_MIN))]
"TARGET_SSE_MATH"
"minss\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "SF")])
(define_insn "*ieee_smaxsf3"
[(set (match_operand:SF 0 "register_operand" "=x")
(unspec:SF [(match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonimmediate_operand" "xm")]
UNSPEC_IEEE_MAX))]
"TARGET_SSE_MATH"
"maxss\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "SF")])
(define_insn "*ieee_smindf3"
[(set (match_operand:DF 0 "register_operand" "=x")
(unspec:DF [(match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "nonimmediate_operand" "xm")]
UNSPEC_IEEE_MIN))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"minsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "DF")])
(define_insn "*ieee_smaxdf3"
[(set (match_operand:DF 0 "register_operand" "=x")
(unspec:DF [(match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "nonimmediate_operand" "xm")]
UNSPEC_IEEE_MAX))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"maxsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "DF")])
;; Conditional addition patterns
(define_expand "addqicc"
[(match_operand:QI 0 "register_operand" "")
......
......@@ -773,6 +773,47 @@
[(set_attr "type" "sselog")
(set_attr "mode" "V4SF")])
;; Also define scalar versions. These are used for abs, neg, and
;; conditional move. Using subregs into vector modes causes regiser
;; allocation lossage. These patterns do not allow memory operands
;; because the native instructions read the full 128-bits.
(define_insn "*andsf3"
[(set (match_operand:SF 0 "register_operand" "=x")
(and:SF (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "register_operand" "x")))]
"TARGET_SSE"
"andps\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog")
(set_attr "mode" "V4SF")])
(define_insn "*nandsf3"
[(set (match_operand:SF 0 "register_operand" "=x")
(and:SF (not:SF (match_operand:SF 1 "register_operand" "0"))
(match_operand:SF 2 "register_operand" "x")))]
"TARGET_SSE"
"andnps\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog")
(set_attr "mode" "V4SF")])
(define_insn "*iorsf3"
[(set (match_operand:SF 0 "register_operand" "=x")
(ior:SF (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "register_operand" "x")))]
"TARGET_SSE"
"orps\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog")
(set_attr "mode" "V4SF")])
(define_insn "*xorsf3"
[(set (match_operand:SF 0 "register_operand" "=x")
(xor:SF (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "register_operand" "x")))]
"TARGET_SSE"
"xorps\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog")
(set_attr "mode" "V4SF")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel single-precision floating point conversion operations
......@@ -1624,7 +1665,7 @@
[(set (match_operand:V2DF 0 "register_operand" "=x")
(and:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
(match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE2 && ix86_binary_operator_ok (AND, V4SFmode, operands)"
"TARGET_SSE2 && ix86_binary_operator_ok (AND, V2DFmode, operands)"
"andpd\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog")
(set_attr "mode" "V2DF")])
......@@ -1670,6 +1711,47 @@
[(set_attr "type" "sselog")
(set_attr "mode" "V2DF")])
;; Also define scalar versions. These are used for abs, neg, and
;; conditional move. Using subregs into vector modes causes regiser
;; allocation lossage. These patterns do not allow memory operands
;; because the native instructions read the full 128-bits.
(define_insn "*anddf3"
[(set (match_operand:DF 0 "register_operand" "=x")
(and:DF (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "register_operand" "x")))]
"TARGET_SSE2"
"andpd\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog")
(set_attr "mode" "V2DF")])
(define_insn "*nanddf3"
[(set (match_operand:DF 0 "register_operand" "=x")
(and:DF (not:DF (match_operand:DF 1 "register_operand" "0"))
(match_operand:DF 2 "register_operand" "x")))]
"TARGET_SSE2"
"andnpd\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog")
(set_attr "mode" "V2DF")])
(define_insn "*iordf3"
[(set (match_operand:DF 0 "register_operand" "=x")
(ior:DF (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "register_operand" "x")))]
"TARGET_SSE2"
"orpd\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog")
(set_attr "mode" "V2DF")])
(define_insn "*xordf3"
[(set (match_operand:DF 0 "register_operand" "=x")
(xor:DF (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "register_operand" "x")))]
"TARGET_SSE2"
"xorpd\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog")
(set_attr "mode" "V2DF")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel double-precision floating point conversion operations
......
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