This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: PPro patch for egcs
- To: john at feith dot com (John Wehle)
- Subject: Re: PPro patch for egcs
- From: hjl at lucon dot org (H.J. Lu)
- Date: Wed, 3 Jun 1998 23:17:32 -0700 (PDT)
- Cc: law at cygnus dot com, egcs at cygnus dot com
>
> >> It also occurs to me that there may be a problem with the floating
> >> point conditional move instructions which (I just noticed) do not
> >> support checking the overflow flag.
> >>
> >
> > There is no overflow in floating point on x86. You have Inf and
> > FP exception. But we do have to handle unordered comparison for FP.
>
> I'm not refering to a floating point comparison ... I'm refering to
> an integer comparison controlling a floating point move. In any
Ooops.
> event I've just submitted a patch for the problem.
>
Here is my new patch. It fixes a few PPro bugs.
Thanks.
H.J.
----
Wed Jun 3 21:39:24 1998 H.J. Lu (hjl@gnu.org)
* config/i386/i386.c (output_fp_conditional_move): New function
to output floating point conditional move.
(output_int_conditional_move): New function to output integer
conditional move.
* config/i386/i386.md (movsicci+5, movhicc+5, movdicc+5): Call
output_int_conditional_move () to output int conditional move.
(movsfcc+5, movdfcc+5, movxfcc+5): Call
output_fp_conditional_move () to output floating point
conditional move.
Tue May 19 06:51:19 1998 H.J. Lu (hjl@gnu.org)
* config/i386/i386.c (notice_update_cc, output_float_compare):
Enable TARGET_CMOVE support.
Wed May 13 17:36:28 1998 H.J. Lu (hjl@gnu.org)
* reg-stack.c (subst_stack_regs_pat): Make sure the top of
stack is the destination for conditional move insn.
Mon May 11 08:04:17 1998 H.J. Lu (hjl@gnu.org)
* config/i386/i386.c (output_float_compare): Fix the unordered
comparison for IEEE math and CC_FCOMI.
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.
Index: config/i386/i386.c
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.1.1.17
diff -u -p -r1.1.1.17 i386.c
--- config/i386/i386.c 1998/05/22 14:05:25 1.1.1.17
+++ config/i386/i386.c 1998/06/04 04:36:44
@@ -3097,7 +3097,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:
@@ -3109,7 +3112,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:
@@ -3691,7 +3697,7 @@ notice_update_cc (exp)
if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
{
cc_status.flags |= CC_IN_80387;
- if (0 && TARGET_CMOVE && stack_regs_mentioned_p
+ if (TARGET_CMOVE && stack_regs_mentioned_p
(XEXP (SET_SRC (XVECEXP (exp, 0, 0)), 1)))
cc_status.flags |= CC_FCOMI;
}
@@ -4021,7 +4027,7 @@ output_float_compare (insn, operands)
int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
rtx tmp;
- if (0 && TARGET_CMOVE && STACK_REG_P (operands[1]))
+ if (TARGET_CMOVE && STACK_REG_P (operands[1]))
{
cc_status.flags |= CC_FCOMI;
cc_prev_status.flags &= ~CC_TEST_AX;
@@ -4055,6 +4061,18 @@ output_float_compare (insn, operands)
{
output_asm_insn (AS2 (fucomip,%y1,%0), operands);
output_asm_insn (AS1 (fstp, %y0), operands);
+
+ if (TARGET_IEEE_FP)
+ {
+ /* It is very tricky. We have to do it right. */
+ rtx xops [1];
+
+ xops [0] = gen_rtx_REG (QImode, 0);
+ output_asm_insn (AS1 (setne,%b0), xops);
+ output_asm_insn (AS1 (setp,%h0), xops);
+ output_asm_insn (AS2 (or%B0,%h0,%b0), xops);
+ }
+
return "";
}
else
@@ -4096,6 +4114,17 @@ output_float_compare (insn, operands)
else if (cc_status.flags & CC_FCOMI)
{
output_asm_insn (strcat (buf, AS2 (%z1,%y1,%0)), operands);
+ if (unordered_compare && TARGET_IEEE_FP)
+ {
+ /* It is very tricky. We have to do it right. */
+ rtx xops [1];
+
+ xops [0] = gen_rtx_REG (QImode, 0);
+ output_asm_insn (AS1 (setne,%b0), xops);
+ output_asm_insn (AS1 (setp,%h0), xops);
+ output_asm_insn (AS2 (or%B0,%h0,%b0), xops);
+ }
+
return "";
}
else
@@ -5129,6 +5158,127 @@ 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[];
+{
+ int code = GET_CODE (operands[1]);
+
+ /* This is very tricky. We have to do it right. For a code segement
+ like:
+
+ int foo;
+ double bar;
+ ....
+ foo = foo - x;
+ if (foo >= 0)
+ bar = y;
+
+ final_scan_insn () may delete the insn which sets CC. We have to
+ tell final_scan_insn () if it should be reinserted. When CODE is
+ GT or LE, we have to check the CC_NO_OVERFLOW bit and return
+ NULL_PTR to tell final to reinsert the test insn because the
+ conditional move cannot be handled properly without it. */
+ if ((code == GT || code == LE)
+ && (cc_prev_status.flags & CC_NO_OVERFLOW))
+ return NULL_PTR;
+
+ switch (which_alternative)
+ {
+ case 0:
+ /* r <- cond ? arg : r */
+ output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+ break;
+
+ case 1:
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (fcmov%f1,%3,%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;
+
+ default:
+ abort ();
+ }
+
+ return "";
+}
+
+char *
+output_int_conditional_move (which_alternative, operands)
+ int which_alternative;
+ rtx operands[];
+{
+ int code = GET_CODE (operands[1]);
+ enum machine_mode mode;
+ rtx xops[4];
+
+ /* This is very tricky. We have to do it right. For a code segement
+ like:
+
+ int foo, bar;
+ ....
+ foo = foo - x;
+ if (foo >= 0)
+ bar = y;
+
+ final_scan_insn () may delete the insn which sets CC. We have to
+ tell final_scan_insn () if it should be reinserted. When CODE is
+ GT or LE, we have to check the CC_NO_OVERFLOW bit and return
+ NULL_PTR to tell final to reinsert the test insn because the
+ conditional move cannot be handled properly without it. */
+ if ((code == GT || code == LE)
+ && (cc_prev_status.flags & CC_NO_OVERFLOW))
+ return NULL_PTR;
+
+ mode = GET_MODE (operands [0]);
+ if (mode == DImode)
+ {
+ xops [0] = gen_rtx_SUBREG (SImode, operands [0], 1);
+ xops [1] = operands [1];
+ xops [2] = gen_rtx_SUBREG (SImode, operands [2], 1);
+ xops [3] = gen_rtx_SUBREG (SImode, operands [3], 1);
+ }
+
+ switch (which_alternative)
+ {
+ case 0:
+ /* r <- cond ? arg : r */
+ output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+ if (mode == DImode)
+ output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
+ break;
+
+ case 1:
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+ if (mode == DImode)
+ output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
+ break;
+
+ case 2:
+ /* rm <- cond ? arg1 : arg2 */
+ output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+ output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+ if (mode == DImode)
+ {
+ output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
+ output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
+ }
+ break;
+
+ default:
+ abort ();
+ }
return "";
}
Index: config/i386/i386.md
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.1.1.17
diff -u -p -r1.1.1.17 i386.md
--- config/i386/i386.md 1998/06/01 14:19:53 1.1.1.17
+++ config/i386/i386.md 1998/06/03 23:57:59
@@ -7307,35 +7307,7 @@ byte_xor_operation:
(match_operand:SI 2 "nonimmediate_operand" "rm,0,rm")
(match_operand:SI 3 "nonimmediate_operand" "0,rm,rm")))]
"TARGET_CMOVE && reload_completed"
- "*
-{
-
- switch (which_alternative)
- {
- case 0:
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- break;
-
- case 1:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- break;
-
- case 2:
- /* r <- cond ? arg1 : arg2 */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- break;
-
- default:
- abort();
- /* NOTREACHED */
- break;
- }
-
- RET;
-}")
+ "* return output_int_conditional_move (which_alternative, operands);")
(define_expand "movhicc"
[(set (match_operand:HI 0 "register_operand" "")
@@ -7410,36 +7382,8 @@ byte_xor_operation:
(match_operand:HI 2 "nonimmediate_operand" "rm,0,rm")
(match_operand:HI 3 "nonimmediate_operand" "0,rm,rm")))]
"TARGET_CMOVE && reload_completed"
- "*
-{
-
- switch (which_alternative)
- {
- case 0:
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- break;
-
- case 1:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- break;
-
- case 2:
- /* r <- cond ? arg1 : arg2 */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- break;
-
- default:
- abort();
- /* NOTREACHED */
- break;
- }
+ "* return output_int_conditional_move (which_alternative, operands);")
- RET;
-}")
-
(define_expand "movsfcc"
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (match_operand 1 "comparison_operator" "")
@@ -7512,35 +7456,7 @@ byte_xor_operation:
(match_operand:SF 2 "register_operand" "f,0,f")
(match_operand:SF 3 "register_operand" "0,f,f")))]
"TARGET_CMOVE && reload_completed"
- "*
-{
-
- switch (which_alternative)
- {
- case 0:
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
- break;
-
- case 1:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (fcmov%f1,%3,%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;
-
- default:
- abort();
- /* NOTREACHED */
- break;
- }
-
- RET;
-}")
+ "* return output_fp_conditional_move (which_alternative, operands);")
(define_expand "movdfcc"
[(set (match_operand:DF 0 "register_operand" "")
@@ -7614,35 +7530,7 @@ byte_xor_operation:
(match_operand:DF 2 "register_operand" "f,0,f")
(match_operand:DF 3 "register_operand" "0,f,f")))]
"TARGET_CMOVE && reload_completed"
- "*
-{
-
- switch (which_alternative)
- {
- case 0:
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
- break;
-
- case 1:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (fcmov%f1,%3,%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;
-
- default:
- abort();
- /* NOTREACHED */
- break;
- }
-
- RET;
-}")
+ "* return output_fp_conditional_move (which_alternative, operands);")
(define_expand "movxfcc"
[(set (match_operand:XF 0 "register_operand" "")
@@ -7716,36 +7604,8 @@ byte_xor_operation:
(match_operand:XF 2 "register_operand" "f,0,f")
(match_operand:XF 3 "register_operand" "0,f,f")))]
"TARGET_CMOVE && reload_completed"
- "*
-{
-
- switch (which_alternative)
- {
- case 0:
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
- break;
-
- case 1:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (fcmov%f1,%3,%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;
-
- default:
- abort();
- /* NOTREACHED */
- break;
- }
+ "* return output_fp_conditional_move (which_alternative, operands);")
- RET;
-}")
-
(define_expand "movdicc"
[(set (match_operand:DI 0 "register_operand" "")
(if_then_else:DI (match_operand 1 "comparison_operator" "")
@@ -7818,49 +7678,7 @@ byte_xor_operation:
(match_operand:DI 2 "nonimmediate_operand" "ro,0,ro")
(match_operand:DI 3 "nonimmediate_operand" "0,ro,ro")))]
"TARGET_CMOVE && reload_completed"
- "*
-{
- rtx xops[4];
-
- xops[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- xops[1] = operands[1];
- xops[2] = REG_P (operands[2])
- ? gen_rtx_REG (SImode, REGNO (operands[2]) + 1)
- : adj_offsettable_operand (operands[2], 4);
- xops[3] = REG_P (operands[3])
- ? gen_rtx_REG (SImode, REGNO (operands[3]) + 1)
- : adj_offsettable_operand (operands[3], 4);
-
- switch (which_alternative)
- {
- case 0:
- /* r <- cond ? arg : r */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
- break;
-
- case 1:
- /* r <- cond ? r : arg */
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
- break;
-
- case 2:
- /* r <- cond ? arg1 : arg2 */
- output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
- output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
- break;
-
- default:
- abort();
- /* NOTREACHED */
- break;
- }
-
- RET;
-}")
+ "* return output_int_conditional_move (which_alternative, operands);")
(define_insn "strlensi_unroll"
[(set (match_operand:SI 0 "register_operand" "=&r,&r")
Index: reg-stack.c
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/reg-stack.c,v
retrieving revision 1.1.1.15
diff -u -p -r1.1.1.15 reg-stack.c
--- reg-stack.c 1998/05/06 20:59:12 1.1.1.15
+++ reg-stack.c 1998/06/03 23:57:59
@@ -2344,6 +2344,15 @@ subst_stack_regs_pat (insn, regstack, pa
case IF_THEN_ELSE:
/* This insn requires the top of stack to be the destination. */
+ /* If the comparison operator is an FP comparison operator,
+ it is handled correctly by compare_for_stack_reg () who
+ will move the destination to the top of stack. But if the
+ comparison operator is not an FP comparison operator, we
+ have to handle it here. */
+ if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
+ && REGNO (*dest) != regstack->reg[regstack->top])
+ emit_swap_insn (insn, regstack, *dest);
+
src1 = get_true_reg (&XEXP (SET_SRC (pat), 1));
src2 = get_true_reg (&XEXP (SET_SRC (pat), 2));