This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Integer conditional move on PPro
- To: wilson at cygnus dot com
- Subject: Integer conditional move on PPro
- From: hjl at lucon dot org (H.J. Lu)
- Date: Fri, 8 May 1998 12:23:20 -0700 (PDT)
- Cc: egcs at cygnus dot com
Hi,
The fp conditional move on PPro is bad. But I think the interger
conditional move bug on PPro is different from the fp one. Can you
take a look at the patch enclosed here?
The problem is the interger conditional move doesn't check the
CC_NO_OVERFLOW bit at all. I think this patch fixes it.
Thanks.
--
H.J. Lu (hjl@gnu.org)
---
Fri May 8 07:53:43 1998 H.J. Lu (hjl@gnu.org)
* config/i386/i386.c (put_condition_code): In INT mode, check
cc_prev_status.flags & CC_NO_OVERFLOW for GE and LT.
(output_int_conditional_move): Likewise for GT and LE.
* config/i386/i386.c (movsicc, movhicc, movsicc_1, movhicc_1):
Enable.
Wed May 6 07:35:26 1998 H.J. Lu (hjl@gnu.org)
* config/i386/i386.md (movsicc_1, movhicc_1): Use
output_int_conditional_move ().
(movxfcc_1, movdfcc_1, movxfcc_1): Fix typos, use
output_fp_conditional_move () and allow constants for reload.
* config/i386/i386.c (output_fp_conditional_move): New function
to hanld fp conditional move.
(output_int_conditional_move): New function to handle integer
conditional move.
Mon Mar 16 19:41:27 1998 Jim Wilson <wilson@cygnus.com>
* config/i386/i386.md (movsfcc, movdfcc, movxfcc, movxfcc_1,
movdfcc_1, movxfcc_1): Use "nonimmediate_operand" as predicate.
--- /home/work/gnu/import/egcs/gcc/config/i386/i386.c Thu May 7 08:23:10 1998
+++ ./i386.c Fri May 8 11:50:29 1998
@@ -3089,7 +3098,10 @@ put_condition_code (code, reverse_cc, mo
return;
case GE:
- fputs ("ge", file);
+ if (cc_prev_status.flags & CC_NO_OVERFLOW)
+ fputs ("ns", file);
+ else
+ fputs ("ge", file);
return;
case GT:
@@ -3101,7 +3113,10 @@ put_condition_code (code, reverse_cc, mo
return;
case LT:
- fputs ("l", file);
+ if (cc_prev_status.flags & CC_NO_OVERFLOW)
+ fputs ("s", file);
+ else
+ fputs ("l", file);
return;
case GEU:
@@ -5121,6 +5136,156 @@ output_strlen_unroll (operands)
output_asm_insn (AS1 (inc%L0,%0), xops);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[12]));
+
+ return "";
+}
+
+char *
+output_fp_conditional_move (which_alternative, operands)
+ int which_alternative;
+ rtx operands[];
+{
+ if (which_alternative == 0)
+ {
+ /* r <- cond ? arg : r */
+ output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+ }
+ else if (which_alternative == 1)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+ }
+ else if (which_alternative == 2)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+ output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+ }
+ else if (which_alternative == 3)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ rtx xops[3];
+
+ xops[0] = gen_label_rtx ();
+ xops[1] = gen_label_rtx ();
+ xops[2] = operands[1];
+
+ output_asm_insn ("j%f2 %l0", xops);
+ if (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM)
+ output_asm_insn (AS1 (fld%z2,%y2), operands);
+ else
+ {
+ int conval = standard_80387_constant_p (operands[2]);
+
+ switch (conval)
+ {
+ case 1:
+ fprintf (asm_out_file, "\tfldz\n");
+ break;
+ case 2:
+ fprintf (asm_out_file, "\tfld1\n");
+ break;
+ default:
+ operands[2] = CONST_DOUBLE_MEM (operands[2]);
+ if (GET_CODE (operands[2]) != MEM)
+ abort ();
+ output_asm_insn (AS1 (fld%z2,%y2), operands);
+ break;
+ }
+ }
+ output_asm_insn ("jmp %l1", xops);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[0]));
+ if (STACK_REG_P (operands[3]) || GET_CODE (operands[3]) == MEM)
+ output_asm_insn (AS1 (fld%z3,%y3), operands);
+ else
+ {
+ int conval = standard_80387_constant_p (operands[2]);
+
+ switch (conval)
+ {
+ case 1:
+ fprintf (asm_out_file, "\tfldz\n");
+ break;
+ case 2:
+ fprintf (asm_out_file, "\tfld1\n");
+ break;
+ default:
+ operands[3] = CONST_DOUBLE_MEM (operands[3]);
+ if (GET_CODE (operands[3]) != MEM)
+ abort ();
+ output_asm_insn (AS1 (fld%z3,%y3), operands);
+ break;
+ }
+ }
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[1]));
+ }
+
+ return "";
+}
+
+char *
+output_int_conditional_move (which_alternative, operands)
+ int which_alternative;
+ rtx operands[];
+{
+ int code = GET_CODE (operands[1]);
+
+ if ((code == GT || code == LE)
+ && (cc_prev_status.flags & CC_NO_OVERFLOW))
+ return NULL_PTR;
+
+ if (which_alternative == 0)
+ {
+ /* r <- cond ? arg : r */
+ output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+ }
+ else if (which_alternative == 1)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+ }
+ else if (which_alternative == 2)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+ output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+ }
+ else if (which_alternative == 3)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ rtx xops[3];
+
+ xops[0] = gen_label_rtx ();
+ xops[1] = gen_label_rtx ();
+ xops[2] = operands[1];
+
+ output_asm_insn ("j%c2 %l0", xops);
+ if (! rtx_equal_p (operands[0], operands[2]))
+ {
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (operands[2]) == MEM)
+ {
+ output_asm_insn (AS2 (mov%z2,%2,%4), operands);
+ output_asm_insn (AS2 (mov%z2,%4,%0), operands);
+ }
+ else
+ output_asm_insn (AS2 (mov%z0,%2,%0), operands);
+ }
+ output_asm_insn ("jmp %l1", xops);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[0]));
+ if (! rtx_equal_p (operands[0], operands[3]))
+ {
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (operands[3]) == MEM)
+ {
+ output_asm_insn (AS2 (mov%z3,%3,%4), operands);
+ output_asm_insn (AS2 (mov%z3,%4,%0), operands);
+ }
+ else
+ output_asm_insn (AS2 (mov%z0,%3,%0), operands);
+ }
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[1]));
+ }
return "";
}
--- /home/work/gnu/import/egcs/gcc/config/i386/i386.md Fri May 8 11:08:32 1998
+++ ./i386.md Fri May 8 12:09:17 1998
@@ -7225,12 +7226,6 @@ byte_xor_operation:
/* Conditional move define_insns. */
-;; These are all disabled, because they are buggy. They are all susceptible
-;; to problems with input reloads clobbering the condition code registers.
-;; It appears the only safe way to write a integer/FP conditional move pattern
-;; is to write one which emits both the compare and the cmov, and which can be
-;; split only after reload.
-
(define_expand "movsicc"
[(match_dup 4)
(parallel [(set (match_operand 0 "register_operand" "")
@@ -7238,7 +7233,7 @@ byte_xor_operation:
(match_operand:SI 2 "general_operand" "")
(match_operand:SI 3 "general_operand" "")))
(clobber (match_scratch:SI 4 "=&r"))])]
- "0 && TARGET_CMOVE"
+ "TARGET_CMOVE"
"
{
operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
@@ -7251,7 +7246,7 @@ byte_xor_operation:
(match_operand:HI 2 "general_operand" "")
(match_operand:HI 3 "general_operand" "")))
(clobber (match_scratch:SI 4 "=&r"))])]
- "0 && TARGET_CMOVE"
+ "TARGET_CMOVE"
"
{
operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
@@ -7264,59 +7259,8 @@ byte_xor_operation:
(match_operand:SI 2 "general_operand" "rm,0,rm,g")
(match_operand:SI 3 "general_operand" "0,rm,rm,g")))
(clobber (match_scratch:SI 4 "X,X,X,=&r"))]
- "0 && TARGET_CMOVE"
- "*
-{
- if (which_alternative == 0)
- {
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- }
- else if (which_alternative == 1)
- {
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- }
- else if (which_alternative == 2)
- {
- /* r <- cond ? arg1 : arg2 */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- }
- else if (which_alternative == 3)
- {
- /* r <- cond ? arg1 : arg2 */
- rtx xops[3];
-
- xops[0] = gen_label_rtx ();
- xops[1] = gen_label_rtx ();
- xops[2] = operands[1];
-
- output_asm_insn (\"j%c2 %l0\", xops);
- if (! rtx_equal_p (operands[0], operands[2]))
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
- {
- output_asm_insn (AS2 (mov%z2,%2,%4), operands);
- output_asm_insn (AS2 (mov%z2,%4,%0), operands);
- }
- else
- output_asm_insn (AS2 (mov%z0,%2,%0), operands);
- output_asm_insn (\"jmp %l1\", xops);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
- if (! rtx_equal_p (operands[0], operands[3]))
- {
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
- {
- output_asm_insn (AS2 (mov%z3,%3,%4), operands);
- output_asm_insn (AS2 (mov%z3,%4,%0), operands);
- }
- else
- output_asm_insn (AS2 (mov%z0,%3,%0), operands);
- }
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
- }
- RET;
-}")
+ "TARGET_CMOVE"
+ "* return output_int_conditional_move (which_alternative, operands);")
(define_insn "movhicc_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,&r,rm")
@@ -7325,69 +7269,25 @@ byte_xor_operation:
(match_operand:HI 2 "general_operand" "rm,0,rm,g")
(match_operand:HI 3 "general_operand" "0,rm,rm,g")))
(clobber (match_scratch:SI 4 "X,X,X,=&r"))]
- "0 && TARGET_CMOVE"
- "*
-{
- if (which_alternative == 0)
- {
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- }
- else if (which_alternative == 1)
- {
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- }
- else if (which_alternative == 2)
- {
- /* r <- cond ? arg1 : arg2 */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- }
- else if (which_alternative == 3)
- {
- /* r <- cond ? arg1 : arg2 */
- rtx xops[3];
-
- xops[0] = gen_label_rtx ();
- xops[1] = gen_label_rtx ();
- xops[2] = operands[1];
-
- output_asm_insn (\"j%c2 %l0\", xops);
- if (! rtx_equal_p (operands[0], operands[2]))
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
- {
- output_asm_insn (AS2 (mov%z2,%2,%4), operands);
- output_asm_insn (AS2 (mov%z2,%4,%0), operands);
- }
- else
- output_asm_insn (AS2 (mov%z0,%2,%0), operands);
- output_asm_insn (\"jmp %l1\", xops);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
- if (! rtx_equal_p (operands[0], operands[3]))
- {
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
- {
- output_asm_insn (AS2 (mov%z3,%3,%4), operands);
- output_asm_insn (AS2 (mov%z3,%4,%0), operands);
- }
- else
- output_asm_insn (AS2 (mov%z0,%3,%0), operands);
- }
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
- }
- RET;
-}")
+ "TARGET_CMOVE"
+ "* return output_int_conditional_move (which_alternative, operands);")
+
+;; These are all disabled, because they are buggy. They are all susceptible
+;; to problems with input reloads clobbering the condition code registers.
+;; It appears the only safe way to write a FP conditional move pattern
+;; is to write one which emits both the compare and the cmov, and which can be
+;; split only after reload.
+
;; We need to disable the FP forms of these since they do not support
;; memory as written, but no input reloads are permitted for insns
;; that use cc0. Also, movxfcc is not present.
(define_expand "movsfcc"
[(match_dup 4)
- (set (match_operand 0 "register_operand" "")
+ (set (match_operand 0 "register_operand" "t")
(if_then_else:SF (match_operand 1 "comparison_operator" "")
- (match_operand:SF 2 "register_operand" "")
- (match_operand:SF 3 "register_operand" "")))]
+ (match_operand:SF 2 "nonimmediate_operand" "")
+ (match_operand:SF 3 "nonimmediate_operand" "")))]
"0 && TARGET_CMOVE"
"
{
@@ -7398,8 +7298,8 @@ byte_xor_operation:
[(match_dup 4)
(set (match_operand 0 "register_operand" "t")
(if_then_else:DF (match_operand 1 "comparison_operator" "")
- (match_operand:DF 2 "register_operand" "")
- (match_operand:DF 3 "register_operand" "")))]
+ (match_operand:DF 2 "nonimmediate_operand" "")
+ (match_operand:DF 3 "nonimmediate_operand" "")))]
"0 && TARGET_CMOVE"
"
{
@@ -7410,8 +7310,8 @@ byte_xor_operation:
[(match_dup 4)
(set (match_operand 0 "register_operand" "")
(if_then_else:XF (match_operand 1 "comparison_operator" "")
- (match_operand:XF 2 "register_operand" "")
- (match_operand:XF 3 "register_operand" "")))]
+ (match_operand:XF 2 "nonimmediate_operand" "")
+ (match_operand:XF 3 "nonimmediate_operand" "")))]
"0 && TARGET_CMOVE"
"
{
@@ -7419,66 +7319,31 @@ byte_xor_operation:
}")
(define_insn "movsfcc_1"
- [(set (match_operand:SF 0 "general_operand" "=f,f,&f")
+ [(set (match_operand:SF 0 "register_operand" "=f,=f,=f,=f")
(if_then_else:SF (match_operator 1 "comparison_operator"
[(cc0) (const_int 0)])
- (match_operand:SF 2 "register_operand" "0,f,f")
- (match_operand:SF 3 "register_operand" "f,0,f")))]
+ (match_operand:SF 2 "nonimmediate_operand" "0,f,f,fFm")
+ (match_operand:SF 3 "nonimmediate_operand" "f,0,f,fFm")))]
"0 && TARGET_CMOVE"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
- break;
-
- case 1:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
- break;
-
- case 2:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
- output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
- break;
- }
-
- RET;
-}")
+ "* return output_fp_conditional_move (which_alternative, operands);")
(define_insn "movdfcc_1"
- [(set (match_operand:DF 0 "general_operand" "=f,f,&f")
+ [(set (match_operand:DF 0 "register_operand" "=f,=f,=f,=f")
(if_then_else:DF (match_operator 1 "comparison_operator"
[(cc0) (const_int 0)])
- (match_operand:DF 2 "register_operand" "0,f,f")
- (match_operand:DF 3 "register_operand" "f,0,f")))]
+ (match_operand:DF 2 "nonimmediate_operand" "0,f,f,fFm")
+ (match_operand:DF 3 "nonimmediate_operand" "f,0,f,fFm")))]
"0 && TARGET_CMOVE"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
- break;
+ "* return output_fp_conditional_move (which_alternative, operands);")
- case 1:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
- break;
-
- case 2:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
- output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
- break;
- }
-
- RET;
-}")
+(define_insn "movxfcc_1"
+ [(set (match_operand:XF 0 "register_operand" "=f,=f,=f,=f")
+ (if_then_else:XF (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:XF 2 "nonimmediate_operand" "0,f,f,fFm")
+ (match_operand:XF 3 "nonimmediate_operand" "f,0,f,fFm")))]
+ "0 && TARGET_CMOVE"
+ "* return output_fp_conditional_move (which_alternative, operands);")
(define_insn "strlensi_unroll"
[(set (match_operand:SI 0 "register_operand" "=&r,&r")