Message ID | 20110202232513.GP30899@tyan-ft48-01.lab.bos.redhat.com |
---|---|
State | New |
Headers | show |
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 >
--- 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; +}