This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: More fp bug in egcs


> 
> I believe this is another bug in the same i386 code as my last patch.
> 
> The problem is that the only FP->DImode converstion instruction pops the
> FP stack.  Normally we have both popping and non-popping versions of
> instructions.  The x86 code handles this by aborting if we need to emit
> the non-existent non-popping instruction.  However, this can't work all
> of the time, because it assumes the optimizer always generates optimal
> code.  That isn't safe.  And it is obviously not safe if we are compiling
> without optimization.
> 
> In order to fix this, we need to emulate the missing instruction if gcc
> needs to emit it.  The following patch does this.   If there is a better way
> to do this, then let me know.
> 
> Thu Apr 30 19:28:16 1998  Jim Wilson  <wilson@cygnus.com>
> 
> 	* i386.c (output_fix_trunc): Add code to emulate non-popping DImode
> 	case.
> 
> *** i386.c	Sun Feb 15 11:54:11 1998
> --- /home/wilson/tmp/i386.c	Thu Apr 30 19:26:54 1998
> *************** output_fix_trunc (insn, operands)
> *** 3731,3738 ****
>     int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
>     rtx xops[2];
>   
> !   if (! STACK_TOP_P (operands[1]) ||
> !       (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
>       abort ();
>   
>     xops[0] = GEN_INT (12);
> --- 3731,3737 ----
>     int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
>     rtx xops[2];
>   
> !   if (! STACK_TOP_P (operands[1]))
>       abort ();
>   
>     xops[0] = GEN_INT (12);
> *************** output_fix_trunc (insn, operands)
> *** 3750,3755 ****
> --- 3749,3765 ----
>       {
>         if (stack_top_dies)
>   	output_asm_insn (AS1 (fistp%z0,%0), operands);
> +       else if (GET_MODE (operands[0]) == DImode && ! stack_top_dies)
> + 	{
> + 	  /* There is no DImode version of this without a stack pop, so
> + 	     we must emulate it.  It doesn't matter much what the second
> + 	     instruction is, because the value being pushed on the FP stack
> + 	     is not used except for the following stack popping store.
> + 	     This case can only happen without optimization, so it doesn't
> + 	     matter that it is inefficient.  */
> + 	  output_asm_insn (AS1 (fistp%z0,%0), operands);
> + 	  output_asm_insn (AS1 (fild%z0,%0), operands);
> + 	}
>         else
>   	output_asm_insn (AS1 (fist%z0,%0), operands);
>       }
> 

Here is the trimmed down test case. I am not sure if your patch is
correct. If you take look at the stack RTL dump, you will see SF 1 in

(define_insn ""
  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
        (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "+f")))) 
   (clobber (match_dup 1))
   (clobber (match_operand:SI 2 "memory_operand" "m"))        
   (clobber (match_operand:DI 3 "memory_operand" "m"))
   (clobber (match_scratch:SI 4 "=&q"))]
  "TARGET_80387"
  "* return output_fix_trunc (insn, operands);")                 

is used as the input for the next insn:

;; Insn is not within a basic block
(insn:QI 104 269 272 (parallel[ 
            (set (mem:DI (plus:SI (reg:SI 6 %ebp)
                        (const_int -144)))
                (fix:DI (fix:SF (reg:SF 8 %st(0)))))
            (clobber (reg:SF 8 %st(0)))
            (clobber (mem:SI (plus:SI (reg:SI 6 %ebp)
                        (const_int -4))))
            (clobber (mem:DI (plus:SI (reg:SI 6 %ebp)
                        (const_int -12))))
            (clobber (reg:SI 1 %edx))
        ] ) 117 {fix_truncxfsi2-1} (nil)
    (nil))

;; Insn is not within a basic block
(insn:QI 272 104 275 (set (mem:SF (plus:SI (reg:SI 6 %ebp)
                (const_int -148)))
        (reg:SF 8 %st(0))) -1 (nil)
    (expr_list:REG_DEAD (reg:DF 8 %st(0))
        (nil)))

I don't know if it is correct. Did gcc know %st(0) was not the same
%st(0) before?


Thanks.


-- 
H.J. Lu (hjl@gnu.org)
---
typedef struct _geom_elem {
  double        coeffs[6];
} pGeomDefRec, *pGeomDefPtr;
typedef struct _mpgeombanddef {
	int	yOut;		 
	int	in_width;	 
} mpGeometryBandRec, *mpGeometryBandPtr;
typedef void *pointer;
typedef unsigned char  CARD8;
typedef CARD8 BytePixel;
void  BiGL_B  (OUTP,srcimg,width,sline,pedpvt,pvtband)	pointer OUTP;
pointer *srcimg;
register int width;
int sline;
pGeomDefPtr pedpvt; mpGeometryBandPtr pvtband;
{
  register float s, t, st;
  register int 	isrcline,isrcpix;
  register int 	srcwidth = pvtband->in_width - 1;
  register   BytePixel  val;
  register   BytePixel  *ptrIn, *ptrJn;
  register double a  = pedpvt->coeffs[0];
  register double c  = pedpvt->coeffs[2];
  register double srcpix  = a * ((double)(0.0000))  +	pedpvt->coeffs[1] * (pvtband->yOut + ((double)(0.0000)) ) +	pedpvt->coeffs[4];
  register double srcline = c * ((double)(0.0000))  +	pedpvt->coeffs[3] * (pvtband->yOut + ((double)(0.0000)) ) +	pedpvt->coeffs[5];
  if ( (isrcpix >= 0) && (isrcpix < srcwidth) )
    val =	ptrIn[isrcpix]   * ((float)1. - s - t + st) + ptrIn[isrcpix+1] * (s - st) +	ptrJn[isrcpix]   * (t - st) +	ptrJn[isrcpix+1] * (st) +   (float)0.5 ;
} 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]