diff mbox

Fix FMA_EXPR expansion if fma insn isn't supported (PR target/47312)

Message ID 20110202232513.GP30899@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Feb. 2, 2011, 11:25 p.m. UTC
Hi!

If target setting ends up being different between cc1 and lto1 compilation,
we can have FMA_EXPRs in the IL which ICE during expansion, as there is no
insn for them.  The following patch fixes it by expanding it as a fma{,l,f}
call in that case (x * y + z).  Bootstrapped/regtested on x86_64-linux and
i686-linux, ok for trunk?

2011-02-02  Jakub Jelinek  <jakub@redhat.com>

	PR target/47312
	* expr.c (expand_expr_real_2) <case FMA_EXPR>: If target doesn't expand
	fma, expand FMA_EXPR as fma{,f,l} call.

	* gcc.target/i386/pr47312.c: New test.


	Jakub

Comments

Richard Biener Feb. 3, 2011, 10:05 a.m. UTC | #1
On Thu, Feb 3, 2011 at 12:25 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> If target setting ends up being different between cc1 and lto1 compilation,
> we can have FMA_EXPRs in the IL which ICE during expansion, as there is no
> insn for them.  The following patch fixes it by expanding it as a fma{,l,f}
> call in that case (x * y + z).  Bootstrapped/regtested on x86_64-linux and
> i686-linux, ok for trunk?
>
> 2011-02-02  Jakub Jelinek  <jakub@redhat.com>
>
>        PR target/47312
>        * expr.c (expand_expr_real_2) <case FMA_EXPR>: If target doesn't expand
>        fma, expand FMA_EXPR as fma{,f,l} call.
>
>        * gcc.target/i386/pr47312.c: New test.
>
> --- gcc/expr.c.jj       2011-01-28 20:35:51.000000000 +0100
> +++ gcc/expr.c  2011-02-02 17:34:32.121461641 +0100
> @@ -7695,6 +7695,34 @@ expand_expr_real_2 (sepops ops, rtx targ
>        optab opt = fma_optab;
>        gimple def0, def2;
>
> +       /* If there is no insn for FMA, emit it as __builtin_fma{,f,l}
> +          call.  */
> +       if (optab_handler (fma_optab, mode) == CODE_FOR_nothing)
> +         {
> +           tree fn = built_in_decls[BUILT_IN_FMA], call_expr;
> +
> +           if (fn != NULL_TREE
> +               && mode != TYPE_MODE (TREE_TYPE (TREE_TYPE (fn))))
> +             fn = NULL_TREE;
> +           if (fn == NULL_TREE)
> +             {
> +               fn = built_in_decls[BUILT_IN_FMAF];
> +               if (fn != NULL_TREE
> +                   && mode != TYPE_MODE (TREE_TYPE (TREE_TYPE (fn))))
> +                 fn = NULL_TREE;
> +             }
> +           if (fn == NULL_TREE)
> +             {
> +               fn = built_in_decls[BUILT_IN_FMAL];
> +               if (fn != NULL_TREE
> +                   && mode != TYPE_MODE (TREE_TYPE (TREE_TYPE (fn))))
> +                 fn = NULL_TREE;
> +             }

Ick ;)  Can you use mathfn_built_in for this please?

Otherwise ok.

Thanks,
Richard.

> +           gcc_assert (fn != NULL_TREE);
> +           call_expr = build_call_expr (fn, 3, treeop0, treeop1, treeop2);
> +           return expand_builtin (call_expr, target, subtarget, mode, false);
> +         }
> +
>        def0 = get_def_for_expr (treeop0, NEGATE_EXPR);
>        def2 = get_def_for_expr (treeop2, NEGATE_EXPR);
>
> --- gcc/testsuite/gcc.target/i386/pr47312.c.jj  2011-02-02 17:39:11.600424932 +0100
> +++ gcc/testsuite/gcc.target/i386/pr47312.c     2011-02-02 17:48:59.407388842 +0100
> @@ -0,0 +1,23 @@
> +/* PR target/47312 */
> +/* { dg-do link } */
> +/* { dg-require-effective-target lto } */
> +/* { dg-require-effective-target xop } */
> +/* { dg-options "-O -flto -mno-sse3 -mxop" } */
> +
> +extern double fma (double, double, double);
> +extern float fmaf (float, float, float);
> +extern long double fmal (long double, long double, long double);
> +
> +volatile float f;
> +volatile double d;
> +volatile long double ld;
> +
> +int
> +main ()
> +{
> +  f = fmaf (f, f, f);
> +  d = fma (d, d, d);
> +  ld = fmal (ld, ld, ld);
> +  asm volatile ("" : : "r" (&f), "r" (&d), "r" (&ld) : "memory");
> +  return 0;
> +}
>
>        Jakub
>
diff mbox

Patch

--- gcc/expr.c.jj	2011-01-28 20:35:51.000000000 +0100
+++ gcc/expr.c	2011-02-02 17:34:32.121461641 +0100
@@ -7695,6 +7695,34 @@  expand_expr_real_2 (sepops ops, rtx targ
 	optab opt = fma_optab;
 	gimple def0, def2;
 
+	/* If there is no insn for FMA, emit it as __builtin_fma{,f,l}
+	   call.  */
+	if (optab_handler (fma_optab, mode) == CODE_FOR_nothing)
+	  {
+	    tree fn = built_in_decls[BUILT_IN_FMA], call_expr;
+
+	    if (fn != NULL_TREE
+		&& mode != TYPE_MODE (TREE_TYPE (TREE_TYPE (fn))))
+	      fn = NULL_TREE;
+	    if (fn == NULL_TREE)
+	      {
+		fn = built_in_decls[BUILT_IN_FMAF];
+		if (fn != NULL_TREE
+		    && mode != TYPE_MODE (TREE_TYPE (TREE_TYPE (fn))))
+		  fn = NULL_TREE;
+	      }
+	    if (fn == NULL_TREE)
+	      {
+		fn = built_in_decls[BUILT_IN_FMAL];
+		if (fn != NULL_TREE
+		    && mode != TYPE_MODE (TREE_TYPE (TREE_TYPE (fn))))
+		  fn = NULL_TREE;
+	      }
+	    gcc_assert (fn != NULL_TREE);
+	    call_expr = build_call_expr (fn, 3, treeop0, treeop1, treeop2);
+	    return expand_builtin (call_expr, target, subtarget, mode, false);
+	  }
+
 	def0 = get_def_for_expr (treeop0, NEGATE_EXPR);
 	def2 = get_def_for_expr (treeop2, NEGATE_EXPR);
 
--- gcc/testsuite/gcc.target/i386/pr47312.c.jj	2011-02-02 17:39:11.600424932 +0100
+++ gcc/testsuite/gcc.target/i386/pr47312.c	2011-02-02 17:48:59.407388842 +0100
@@ -0,0 +1,23 @@ 
+/* PR target/47312 */
+/* { dg-do link } */
+/* { dg-require-effective-target lto } */
+/* { dg-require-effective-target xop } */
+/* { dg-options "-O -flto -mno-sse3 -mxop" } */
+
+extern double fma (double, double, double);
+extern float fmaf (float, float, float);
+extern long double fmal (long double, long double, long double);
+
+volatile float f;
+volatile double d;
+volatile long double ld;
+
+int
+main ()
+{
+  f = fmaf (f, f, f);
+  d = fma (d, d, d);
+  ld = fmal (ld, ld, ld);
+  asm volatile ("" : : "r" (&f), "r" (&d), "r" (&ld) : "memory");
+  return 0;
+}