This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
SSE store flag patterns
- To: Richard Henderson <rth at redhat dot com>, gcc-patches at gcc dot gnu dot org, patches at x86-64 dot org
- Subject: SSE store flag patterns
- From: Jan Hubicka <jh at suse dot cz>
- Date: Tue, 27 Feb 2001 13:55:06 +0100
Hi
This patch adds store flag patterns needed for conditional move implementation.
It also cleans up the SSE conditional infratructure somehow.
Tue Feb 27 13:52:00 CET 2001 Jan Hubicka <jh@suse.cz>
* i386.md (sse_setccsf, sse_setccdf): New.
(sse_cmp* patterns): Use '%D' instead of outputtting condition
flag directly.
* i386.c (sse_comparison_operator): Accept the supported unordered
comparses; be ready for fast_math.
* i386.md (print_operand): Support 'D'.
Index: i386.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.220
diff -c -3 -p -r1.220 i386.md
*** i386.md 2001/02/25 13:33:59 1.220
--- i386.md 2001/02/27 12:38:24
***************
*** 9315,9320 ****
--- 9443,9475 ----
[(set_attr "type" "setcc")
(set_attr "mode" "QI")])
+ ;; 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, se we can't represent
+ ;; it directly. Futher 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.
+
+ (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"
+ "cmp%D1ss\\t{%3, %0|%0, %3}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
+
+ (define_insn "*sse_setccdf"
+ [(set (match_operand:DF 0 "register_operand" "=Y")
+ (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"
+ "cmp%D1sd\\t{%3, %0|%0, %3}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "DF")])
;; Basic conditional jump instructions.
;; We ignore the overflow flag for signed branch instructions.
***************
*** 13669,13690 ****
[(match_operand:V4SF 1 "register_operand" "0")
(match_operand:V4SF 2 "nonimmediate_operand" "x")]))]
"TARGET_SSE"
! "*
! {
! switch (GET_CODE (operands[3]))
! {
! case EQ:
! return \"cmpeqps\\t{%2, %0|%0, %2}\";
! case LT:
! return \"cmpltps\\t{%2, %0|%0, %2}\";
! case LE:
! return \"cmpleps\\t{%2, %0|%0, %2}\";
! case UNORDERED:
! return \"cmpunordps\\t{%2, %0|%0, %2}\";
! default:
! abort ();
! }
! }"
[(set_attr "type" "sse")])
(define_insn "maskncmpv4sf3"
--- 14462,14468 ----
[(match_operand:V4SF 1 "register_operand" "0")
(match_operand:V4SF 2 "nonimmediate_operand" "x")]))]
"TARGET_SSE"
! "cmp%D3ps\\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")])
(define_insn "maskncmpv4sf3"
***************
*** 13694,13715 ****
[(match_operand:V4SF 1 "register_operand" "0")
(match_operand:V4SF 2 "nonimmediate_operand" "x")])))]
"TARGET_SSE"
! "*
! {
! switch (GET_CODE (operands[3]))
! {
! case EQ:
! return \"cmpneqps\\t{%2, %0|%0, %2}\";
! case LT:
! return \"cmpnltps\\t{%2, %0|%0, %2}\";
! case LE:
! return \"cmpnleps\\t{%2, %0|%0, %2}\";
! case UNORDERED:
! return \"cmpordps\\t{%2, %0|%0, %2}\";
! default:
! abort ();
! }
! }"
[(set_attr "type" "sse")])
(define_insn "vmmaskcmpv4sf3"
--- 14472,14478 ----
[(match_operand:V4SF 1 "register_operand" "0")
(match_operand:V4SF 2 "nonimmediate_operand" "x")])))]
"TARGET_SSE"
! "cmpn%D3ps\\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")])
(define_insn "vmmaskcmpv4sf3"
***************
*** 13721,13742 ****
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
! "*
! {
! switch (GET_CODE (operands[3]))
! {
! case EQ:
! return \"cmpeqss\\t{%2, %0|%0, %2}\";
! case LT:
! return \"cmpltss\\t{%2, %0|%0, %2}\";
! case LE:
! return \"cmpless\\t{%2, %0|%0, %2}\";
! case UNORDERED:
! return \"cmpunordss\\t{%2, %0|%0, %2}\";
! default:
! abort ();
! }
! }"
[(set_attr "type" "sse")])
(define_insn "vmmaskncmpv4sf3"
--- 14484,14490 ----
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
! "cmp%D3ss\\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")])
(define_insn "vmmaskncmpv4sf3"
***************
*** 13749,13770 ****
(subreg:V4SI (match_dup 1) 0)
(const_int 1)))]
"TARGET_SSE"
! "*
! {
! switch (GET_CODE (operands[3]))
! {
! case EQ:
! return \"cmpneqss\\t{%2, %0|%0, %2}\";
! case LT:
! return \"cmpnltss\\t{%2, %0|%0, %2}\";
! case LE:
! return \"cmpnless\\t{%2, %0|%0, %2}\";
! case UNORDERED:
! return \"cmpordss\\t{%2, %0|%0, %2}\";
! default:
! abort ();
! }
! }"
[(set_attr "type" "sse")])
(define_insn "sse_comi"
--- 14497,14503 ----
(subreg:V4SI (match_dup 1) 0)
(const_int 1)))]
"TARGET_SSE"
! "cmp%D3ss\\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")])
(define_insn "sse_comi"
Index: i386.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.224
diff -c -3 -p -r1.224 i386.c
*** i386.c 2001/02/25 16:35:48 1.224
--- i386.c 2001/02/27 12:49:58
*************** sse_comparison_operator (op, mode)
*** 1318,1324 ****
enum machine_mode mode ATTRIBUTE_UNUSED;
{
enum rtx_code code = GET_CODE (op);
! return code == EQ || code == LT || code == LE || code == UNORDERED;
}
/* Return 1 if OP is a valid comparison operator in valid mode. */
int
--- 1359,1387 ----
enum machine_mode mode ATTRIBUTE_UNUSED;
{
enum rtx_code code = GET_CODE (op);
! switch (code)
! {
! /* Operations supported directly. */
! case EQ:
! case LT:
! case LE:
! case UNORDERED:
! case NE:
! case UNGE:
! case UNGT:
! case ORDERED:
! return 1;
! /* These are equivalent to ones above in non-IEEE comparisons. */
! case UNEQ:
! case UNLT:
! case UNLE:
! case LTGT:
! case GE:
! case GT:
! return !TARGET_IEEE_FP;
! default:
! return 0;
! }
}
/* Return 1 if OP is a valid comparison operator in valid mode. */
int
*************** print_reg (x, code, file)
*** 3326,3332 ****
k -- likewise, print the SImode name of the register.
h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
y -- print "st(0)" instead of "st" as a register.
! m -- print "st(n)" as an mmx register. */
void
print_operand (file, x, code)
--- 3489,3497 ----
k -- likewise, print the SImode name of the register.
h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
y -- print "st(0)" instead of "st" as a register.
! m -- print "st(n)" as an mmx register.
! D -- print condition for SSE cmp instruction.
! */
void
print_operand (file, x, code)
*************** print_operand (file, x, code)
*** 3460,3465 ****
--- 3627,3673 ----
}
return;
+ case 'D':
+ /* Little bit of braindamage here. The SSE compare instructions
+ does use completely different names for the comparisons that the
+ fp conditional moves. */
+ switch (GET_CODE (x))
+ {
+ case EQ:
+ case UNEQ:
+ fputs ("eq", file);
+ break;
+ case LT:
+ case UNLT:
+ fputs ("lt", file);
+ break;
+ case LE:
+ case UNLE:
+ fputs ("le", file);
+ break;
+ case UNORDERED:
+ fputs ("unord", file);
+ break;
+ case NE:
+ case LTGT:
+ fputs ("neq", file);
+ break;
+ case UNGE:
+ case GE:
+ fputs ("nlt", file);
+ break;
+ case UNGT:
+ case GT:
+ fputs ("nle", file);
+ break;
+ case ORDERED:
+ fputs ("ord", file);
+ break;
+ default:
+ abort ();
+ break;
+ }
+ return;
case 'C':
put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 0, 0, file);
return;