> > > Hi, > > > > I am looking into your bug report > > > > http://www.cygnus.com/ml/egcs-bugs/1998-Nov/0476.html > > > > I don't have a real fix yet. But I did find a bug in reg-stack.c which > > would silently generate incorrect code. This patch is a sanity check > > and it will cause compiler to abort on your testcase instead of > > generating buggy asm code. I will work on a real fix when I find more > > time. > > > > Thanks. > > Hi, This is a patch for egcs 1.1.1 which fixes the bug http://www.cygnus.com/ml/egcs-bugs/1998-Nov/0476.html The detailed analysises can be found at http://www.cygnus.com/ml/egcs-bugs/1998-Dec/0475.html http://www.cygnus.com/ml/egcs-bugs/1998-Dec/0481.html If you are using floating point with Pentium Pro optimization, I strongly encourage you to give this patch a try. Thanks. -- H.J. Lu ([EMAIL PROTECTED]) --- Fri Dec 18 06:57:12 1998 H.J. Lu ([EMAIL PROTECTED]) * reg-stack.c (subst_stack_regs_pat): Abort if the destination of a FP conditional move is not on the FP register stack. * config/i386/i386.md (movsfcc, movdfcc, movxfcc): Make sure the target is among the sources. (movsfcc+1, movsfcc+2, movsfcc+3, movsfcc+4, movsfcc+5, movdfcc+1, movdfcc+2, movdfcc+3, movdfcc+4, movdfcc+5, movxfcc+1, movxfcc+2, movxfcc+3, movxfcc+4, movxfcc+5): Disallow patterns where the target is not among the sources. * config/i386/i386.c (output_fp_conditional_move): Remove the third alternative. diff -x CVS -x c-gperf.h -upr /home/work/misc/gnu/import/egcs/gcc/config/i386/i386.c ./config/i386/i386.c --- /home/work/misc/gnu/import/egcs/gcc/config/i386/i386.c Wed Jul 29 07:35:38 1998 +++ ./config/i386/i386.c Fri Dec 18 09:06:53 1998 @@ -5208,12 +5208,6 @@ output_fp_conditional_move (which_altern 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 (); } diff -x CVS -x c-gperf.h -upr /home/work/misc/gnu/import/egcs/gcc/config/i386/i386.md ./config/i386/i386.md --- /home/work/misc/gnu/import/egcs/gcc/config/i386/i386.md Thu Jul 30 08:11:16 1998 +++ ./config/i386/i386.md Fri Dec 18 08:47:30 1998 @@ -7383,6 +7383,15 @@ byte_xor_operation: if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) FAIL; + /* We have to make sure that the target is among the sources so + that it is on the register stack. */ + if (!rtx_equal_p (operands[0], operands[2]) + && !rtx_equal_p (operands[0], operands[3])) + { + emit_insn (gen_movsf (operands[0], operands[2])); + operands[2] = operands[0]; + } + /* The floating point conditional move instructions don't directly support conditions resulting from a signed integer comparison. */ @@ -7411,36 +7420,36 @@ byte_xor_operation: }") (define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f,f,f,f,f") + [(set (match_operand:SF 0 "register_operand" "=f,f,f,f") (if_then_else:SF (match_operator 1 "comparison_operator" - [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m,q,m") - (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn,qmn,qn")]) - (match_operand:SF 4 "register_operand" "f,f,0,0,f,f") - (match_operand:SF 5 "register_operand" "0,0,f,f,f,f")))] + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:SF 4 "register_operand" "f,f,0,0") + (match_operand:SF 5 "register_operand" "0,0,f,f")))] "TARGET_CMOVE && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" "#") (define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f,f,f,f,f") + [(set (match_operand:SF 0 "register_operand" "=f,f,f,f") (if_then_else:SF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "r,m,r,m,r,m") - (match_operand 3 "general_operand" "rmi,ri,rmi,ri,rmi,ri")]) - (match_operand:SF 4 "register_operand" "f,f,0,0,f,f") - (match_operand:SF 5 "register_operand" "0,0,f,f,f,f")))] + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:SF 4 "register_operand" "f,f,0,0") + (match_operand:SF 5 "register_operand" "0,0,f,f")))] "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" "#") (define_split - [(set (match_operand:SF 0 "register_operand" "=f,f,f") + [(set (match_operand:SF 0 "register_operand" "=f,f") (if_then_else:SF (match_operator 1 "comparison_operator" [(match_operand 2 "nonimmediate_operand" "") (const_int 0)]) - (match_operand:SF 3 "register_operand" "f,0,f") - (match_operand:SF 4 "register_operand" "0,f,f")))] + (match_operand:SF 3 "register_operand" "f,0") + (match_operand:SF 4 "register_operand" "0,f")))] "TARGET_CMOVE && reload_completed" [(set (cc0) (match_dup 2)) @@ -7450,12 +7459,12 @@ byte_xor_operation: "") (define_split - [(set (match_operand:SF 0 "register_operand" "=f,f,f") + [(set (match_operand:SF 0 "register_operand" "=f,f") (if_then_else:SF (match_operator 1 "comparison_operator" [(match_operand 2 "nonimmediate_operand" "") (match_operand 3 "general_operand" "")]) - (match_operand:SF 4 "register_operand" "f,0,f") - (match_operand:SF 5 "register_operand" "0,f,f")))] + (match_operand:SF 4 "register_operand" "f,0") + (match_operand:SF 5 "register_operand" "0,f")))] "TARGET_CMOVE && reload_completed" [(set (cc0) (compare (match_dup 2) (match_dup 3))) (set (match_dup 0) @@ -7464,11 +7473,11 @@ byte_xor_operation: "") (define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f,f") + [(set (match_operand:SF 0 "register_operand" "=f,f") (if_then_else:SF (match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) - (match_operand:SF 2 "register_operand" "f,0,f") - (match_operand:SF 3 "register_operand" "0,f,f")))] + (match_operand:SF 2 "register_operand" "f,0") + (match_operand:SF 3 "register_operand" "0,f")))] "TARGET_CMOVE && reload_completed" "* return output_fp_conditional_move (which_alternative, operands);") @@ -7485,6 +7494,15 @@ byte_xor_operation: if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) FAIL; + /* We have to make sure that the target is among the sources so + that it is on the register stack. */ + if (!rtx_equal_p (operands[0], operands[2]) + && !rtx_equal_p (operands[0], operands[3])) + { + emit_insn (gen_movdf (operands[0], operands[2])); + operands[2] = operands[0]; + } + /* The floating point conditional move instructions don't directly support conditions resulting from a signed integer comparison. */ @@ -7513,36 +7531,36 @@ byte_xor_operation: }") (define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f,f,f,f,f") + [(set (match_operand:DF 0 "register_operand" "=f,f,f,f") (if_then_else:DF (match_operator 1 "comparison_operator" - [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m,q,m") - (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn,qmn,qn")]) - (match_operand:DF 4 "register_operand" "f,f,0,0,f,f") - (match_operand:DF 5 "register_operand" "0,0,f,f,f,f")))] + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:DF 4 "register_operand" "f,f,0,0") + (match_operand:DF 5 "register_operand" "0,0,f,f")))] "TARGET_CMOVE && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" "#") (define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f,f,f,f,f") + [(set (match_operand:DF 0 "register_operand" "=f,f,f,f") (if_then_else:DF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "r,m,r,m,r,m") - (match_operand 3 "general_operand" "rmi,ri,rmi,ri,rmi,ri")]) - (match_operand:DF 4 "register_operand" "f,f,0,0,f,f") - (match_operand:DF 5 "register_operand" "0,0,f,f,f,f")))] + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:DF 4 "register_operand" "f,f,0,0") + (match_operand:DF 5 "register_operand" "0,0,f,f")))] "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" "#") (define_split - [(set (match_operand:DF 0 "register_operand" "=f,f,f") + [(set (match_operand:DF 0 "register_operand" "=f,f") (if_then_else:DF (match_operator 1 "comparison_operator" [(match_operand 2 "nonimmediate_operand" "") (const_int 0)]) - (match_operand:DF 3 "register_operand" "f,0,f") - (match_operand:DF 4 "register_operand" "0,f,f")))] + (match_operand:DF 3 "register_operand" "f,0") + (match_operand:DF 4 "register_operand" "0,f")))] "TARGET_CMOVE && reload_completed" [(set (cc0) (match_dup 2)) @@ -7552,12 +7570,12 @@ byte_xor_operation: "") (define_split - [(set (match_operand:DF 0 "register_operand" "=f,f,f") + [(set (match_operand:DF 0 "register_operand" "=f,f") (if_then_else:DF (match_operator 1 "comparison_operator" [(match_operand 2 "nonimmediate_operand" "") (match_operand 3 "general_operand" "")]) - (match_operand:DF 4 "register_operand" "f,0,f") - (match_operand:DF 5 "register_operand" "0,f,f")))] + (match_operand:DF 4 "register_operand" "f,0") + (match_operand:DF 5 "register_operand" "0,f")))] "TARGET_CMOVE && reload_completed" [(set (cc0) (compare (match_dup 2) (match_dup 3))) (set (match_dup 0) @@ -7566,11 +7584,11 @@ byte_xor_operation: "") (define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f,f") + [(set (match_operand:DF 0 "register_operand" "=f,f") (if_then_else:DF (match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) - (match_operand:DF 2 "register_operand" "f,0,f") - (match_operand:DF 3 "register_operand" "0,f,f")))] + (match_operand:DF 2 "register_operand" "f,0") + (match_operand:DF 3 "register_operand" "0,f")))] "TARGET_CMOVE && reload_completed" "* return output_fp_conditional_move (which_alternative, operands);") @@ -7587,6 +7605,15 @@ byte_xor_operation: if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) FAIL; + /* We have to make sure that the target is among the sources so + that it is on the register stack. */ + if (!rtx_equal_p (operands[0], operands[2]) + && !rtx_equal_p (operands[0], operands[3])) + { + emit_insn (gen_movxf (operands[0], operands[2])); + operands[2] = operands[0]; + } + /* The floating point conditional move instructions don't directly support conditions resulting from a signed integer comparison. */ @@ -7615,36 +7642,36 @@ byte_xor_operation: }") (define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f,f,f,f,f") + [(set (match_operand:XF 0 "register_operand" "=f,f,f,f") (if_then_else:XF (match_operator 1 "comparison_operator" - [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m,q,m") - (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn,qmn,qn")]) - (match_operand:XF 4 "register_operand" "f,f,0,0,f,f") - (match_operand:XF 5 "register_operand" "0,0,f,f,f,f")))] + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:XF 4 "register_operand" "f,f,0,0") + (match_operand:XF 5 "register_operand" "0,0,f,f")))] "TARGET_CMOVE && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" "#") (define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f,f,f,f,f") + [(set (match_operand:XF 0 "register_operand" "=f,f,f,f") (if_then_else:XF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "r,m,r,m,r,m") - (match_operand 3 "general_operand" "rmi,ri,rmi,ri,rmi,ri")]) - (match_operand:XF 4 "register_operand" "f,f,0,0,f,f") - (match_operand:XF 5 "register_operand" "0,0,f,f,f,f")))] + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:XF 4 "register_operand" "f,f,0,0") + (match_operand:XF 5 "register_operand" "0,0,f,f")))] "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" "#") (define_split - [(set (match_operand:XF 0 "register_operand" "=f,f,f") + [(set (match_operand:XF 0 "register_operand" "=f,f") (if_then_else:XF (match_operator 1 "comparison_operator" [(match_operand 2 "nonimmediate_operand" "") (const_int 0)]) - (match_operand:XF 3 "register_operand" "f,0,f") - (match_operand:XF 4 "register_operand" "0,f,f")))] + (match_operand:XF 3 "register_operand" "f,0") + (match_operand:XF 4 "register_operand" "0,f")))] "TARGET_CMOVE && reload_completed" [(set (cc0) (match_dup 2)) @@ -7654,12 +7681,12 @@ byte_xor_operation: "") (define_split - [(set (match_operand:XF 0 "register_operand" "=f,f,f") + [(set (match_operand:XF 0 "register_operand" "=f,f") (if_then_else:XF (match_operator 1 "comparison_operator" [(match_operand 2 "nonimmediate_operand" "") (match_operand 3 "general_operand" "")]) - (match_operand:XF 4 "register_operand" "f,0,f") - (match_operand:XF 5 "register_operand" "0,f,f")))] + (match_operand:XF 4 "register_operand" "f,0") + (match_operand:XF 5 "register_operand" "0,f")))] "TARGET_CMOVE && reload_completed" [(set (cc0) (compare (match_dup 2) (match_dup 3))) (set (match_dup 0) @@ -7668,11 +7695,11 @@ byte_xor_operation: "") (define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f,f") + [(set (match_operand:XF 0 "register_operand" "=f,f") (if_then_else:XF (match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) - (match_operand:XF 2 "register_operand" "f,0,f") - (match_operand:XF 3 "register_operand" "0,f,f")))] + (match_operand:XF 2 "register_operand" "f,0") + (match_operand:XF 3 "register_operand" "0,f")))] "TARGET_CMOVE && reload_completed" "* return output_fp_conditional_move (which_alternative, operands);") diff -x CVS -x c-gperf.h -upr /home/work/misc/gnu/import/egcs/gcc/reg-stack.c ./reg-stack.c --- /home/work/misc/gnu/import/egcs/gcc/reg-stack.c Thu Oct 8 12:10:13 1998 +++ ./reg-stack.c Wed Dec 16 14:45:00 1998 @@ -2349,6 +2349,10 @@ subst_stack_regs_pat (insn, regstack, pa break; case IF_THEN_ELSE: + /* dest has to be on stack. */ + if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG) + abort (); + /* This insn requires the top of stack to be the destination. */ /* If the comparison operator is an FP comparison operator, @@ -2402,9 +2406,7 @@ subst_stack_regs_pat (insn, regstack, pa } } - /* Make dest the top of stack. Add dest to regstack if not present. */ - if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG) - regstack->reg[++regstack->top] = REGNO (*dest); + /* Make dest the top of stack. */ SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); replace_reg (dest, FIRST_STACK_REG);
