This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fp conversions optimizations part 3
- From: Jan Hubicka <jh at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com
- Date: Sun, 10 Nov 2002 19:24:33 +0100
- Subject: 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