This is the mail archive of the gcc-patches@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]
Other format: [Raw text]

Fp conversions optimizations part 3


Hi,
this patch adds the simplification into combine.  It handles similar cases as I
am shooting for in combine, but is limited.  We can't handle the binary
operations as we must fold 4 operations at time except for x87 where we create
temporary instruction because we ignore float extends.

Also we can't simplify a=sqrt(a) for global float variable because we construct
sqrt pattern both reading and writing memory and split it incorrectly (splitter
in md file would accomplish this, perhaps I will add one, but I guss fold-const
side will handle this better).
I will experiment with changing the find_split_point in next patch.

We also need -ffast-math to do something for sqrt.

/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -msse2 -mfpmath=sse -march=athlon -ffast-math" } */
/* { dg-final { scan-assembler "sqrtss" } } */
float a;
t()
{
 double b=a+a;
 a=sqrt(b);
}

/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -mfpmath=i387 -march=athlon" } */
/* { dg-final { scan-assembler-not "fstps.*bp" } } */
/* Check that the conversion has been folded by combine.  This happends only
   for i387 math because otherwise it requires combining of 4 instructions.  */
float a;
t()
{
 float b=(double)(a+1)+(a+2);
 a=b+1;
}

Sun Nov 10 20:48:48 CET 2002  Jan Hubicka  <jh@suse.cz>
	* combine.c (combine_sinplify_rtx): Avoid some unnecesary FP
	conversions.
*** combine.c.old	Sun Nov 10 20:03:37 2002
--- combine.c	Sun Nov 10 21:24:25 2002
*************** combine_simplify_rtx (x, op0_mode, last,
*** 4145,4164 ****
  	return XEXP (XEXP (x, 0), 0);
  
        /* (float_truncate:SF (OP:DF (float_extend:DF foo:sf))) is
! 	 (OP:SF foo:SF) if OP is NEG or ABS.  */
        if ((GET_CODE (XEXP (x, 0)) == ABS
! 	   || GET_CODE (XEXP (x, 0)) == NEG)
  	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == FLOAT_EXTEND
  	  && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode)
  	return simplify_gen_unary (GET_CODE (XEXP (x, 0)), mode,
  				   XEXP (XEXP (XEXP (x, 0), 0), 0), mode);
  
        /* (float_truncate:SF (subreg:DF (float_truncate:SF X) 0))
  	 is (float_truncate:SF x).  */
        if (GET_CODE (XEXP (x, 0)) == SUBREG
  	  && subreg_lowpart_p (XEXP (x, 0))
  	  && GET_CODE (SUBREG_REG (XEXP (x, 0))) == FLOAT_TRUNCATE)
  	return SUBREG_REG (XEXP (x, 0));
        break;
  
  #ifdef HAVE_cc0
--- 4145,4207 ----
  	return XEXP (XEXP (x, 0), 0);
  
        /* (float_truncate:SF (OP:DF (float_extend:DF foo:sf))) is
! 	 (OP:SF foo:SF) if OP is NEG, ABS or SQRT.  */
        if ((GET_CODE (XEXP (x, 0)) == ABS
! 	   || GET_CODE (XEXP (x, 0)) == NEG
! 	   || GET_CODE (XEXP (x, 0)) == SQRT)
  	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == FLOAT_EXTEND
  	  && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode)
  	return simplify_gen_unary (GET_CODE (XEXP (x, 0)), mode,
  				   XEXP (XEXP (XEXP (x, 0), 0), 0), mode);
  
+       /* (float_truncate:SF (OP:DF (foo:DF))
+ 	 is (OP:SF (float_truncate (foo:DF))) when OP is NEG or ABS.  */
+       if (GET_CODE (XEXP (x, 0)) == ABS
+ 	  || GET_CODE (XEXP (x, 0)) == NEG)
+ 	return simplify_gen_unary (GET_CODE (XEXP (x, 0)), mode,
+ 				   simplify_gen_unary (FLOAT_TRUNCATE,
+ 						       mode,
+ 						       XEXP (XEXP (x, 0), 0),
+ 						       GET_MODE (XEXP (XEXP (x,
+ 									     0),
+ 								       0))),
+ 				   mode);
+ 
        /* (float_truncate:SF (subreg:DF (float_truncate:SF X) 0))
  	 is (float_truncate:SF x).  */
        if (GET_CODE (XEXP (x, 0)) == SUBREG
  	  && subreg_lowpart_p (XEXP (x, 0))
  	  && GET_CODE (SUBREG_REG (XEXP (x, 0))) == FLOAT_TRUNCATE)
  	return SUBREG_REG (XEXP (x, 0));
+ 
+       /* (float_truncate:SF (OP:DF (float_extend:DF (foo:SF)) (float_extend:DF (foo2:SF))))
+ 	 is (OP_SF (foo:SF) (foo2:SF)) in most cases.  */
+       if ((GET_CODE (XEXP (x, 0)) == PLUS
+ 	   || GET_CODE (XEXP (x, 0)) == MINUS
+ 	   || GET_CODE (XEXP (x, 0)) == MULT
+ 	   || GET_CODE (XEXP (x, 0)) == DIV)
+ 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == FLOAT_EXTEND
+ 	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == FLOAT_EXTEND)
+ 	{
+ 	  enum machine_mode new_mode = mode;
+ 	  rtx op0 = XEXP (XEXP (XEXP (x, 0), 0), 0);
+ 	  rtx op1 = XEXP (XEXP (XEXP (x, 0), 1), 0);
+ 	  rtx exp;
+ 
+ 	  if (GET_MODE_BITSIZE (GET_MODE (op0)) > GET_MODE_BITSIZE (new_mode))
+ 	     new_mode = GET_MODE (op0);
+ 	  if (GET_MODE_BITSIZE (GET_MODE (op1)) > GET_MODE_BITSIZE (new_mode))
+ 	     new_mode = GET_MODE (op1);
+ 	  if (GET_MODE (op0) != new_mode)
+ 	    op0 = simplify_gen_unary (FLOAT_EXTEND, mode, op0, GET_MODE (op0));
+ 	  if (GET_MODE (op1) != new_mode)
+ 	    op0 = simplify_gen_unary (FLOAT_EXTEND, mode, op1, GET_MODE (op0));
+ 	  exp = simplify_gen_binary (GET_CODE (XEXP (x, 0)), new_mode, op0, op1);
+ 	  if (new_mode != mode)
+ 	    return simplify_gen_unary (FLOAT_TRUNCATE, mode, exp, new_mode);
+ 	  else
+ 	    return exp;
+ 	}
        break;
  
  #ifdef HAVE_cc0


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