On December 30, 2017 8:35:09 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> wrote: >Hi! > >The comment on convert_modes says: > Both modes may be floating, or both integer. >but as the testcase shows, with a MEM_REF with a different mode class >than a VAR_DECL as its operand we can end up with e.g. floating point >vs. >integral mode etc. and convert_modes doesn't handle those cases. > >This patch uses simplify_gen_subreg in those case first. > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for >trunk/7.3?
OK. Richard. >2017-12-30 Jakub Jelinek <ja...@redhat.com> > > PR middle-end/83608 > * expr.c (store_expr_with_bounds): Use simplify_gen_subreg instead of > convert_modes if target mode has the right side, but different mode > class. > > * g++.dg/opt/pr83608.C: New test. > >--- gcc/expr.c.jj 2017-12-30 14:35:52.095877981 +0100 >+++ gcc/expr.c 2017-12-30 14:36:06.268882813 +0100 >@@ -5638,8 +5638,21 @@ store_expr_with_bounds (tree exp, rtx ta > if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode > && TREE_CODE (exp) != ERROR_MARK > && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))) >- temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE >(exp)), >- temp, TYPE_UNSIGNED (TREE_TYPE (exp))); >+ { >+ if (GET_MODE_CLASS (GET_MODE (target)) >+ != GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) >+ && GET_MODE_BITSIZE (GET_MODE (target)) >+ == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp)))) >+ { >+ rtx t = simplify_gen_subreg (GET_MODE (target), temp, >+ TYPE_MODE (TREE_TYPE (exp)), 0); >+ if (t) >+ temp = t; >+ } >+ if (GET_MODE (temp) == VOIDmode) >+ temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)), >+ temp, TYPE_UNSIGNED (TREE_TYPE (exp))); >+ } > > /* If value was not generated in the target, store it there. > Convert the value to TARGET's type first if necessary and emit the >--- gcc/testsuite/g++.dg/opt/pr83608.C.jj 2017-12-30 14:36:52.323898522 >+0100 >+++ gcc/testsuite/g++.dg/opt/pr83608.C 2017-12-30 14:00:12.811195532 >+0100 >@@ -0,0 +1,28 @@ >+// PR middle-end/83608 >+// { dg-do compile } >+// { dg-options "-O2" } >+ >+template <typename> class B; >+template <> struct B<float> >+{ >+ float foo () { return __real__ b; } >+ _Complex double b; >+}; >+ >+void bar (int); >+ >+template <class T> >+void >+baz () >+{ >+ B<T> h; >+ T *a = (T *) &h; >+ a[0] = a[1] = 6; >+ h.foo () ? void () : bar (7); >+} >+ >+int >+main () >+{ >+ baz<float> (); >+} > > Jakub