diff mbox series

[RFC] extend DECL_GIMPLE_REG_P to all types

Message ID nycvar.YFH.7.76.2004221254420.830@zhemvz.fhfr.qr
State New
Headers show
Series [RFC] extend DECL_GIMPLE_REG_P to all types | expand

Commit Message

Richard Biener April 22, 2020, 10:56 a.m. UTC
This extends DECL_GIMPLE_REG_P to all types so we can clear
TREE_ADDRESSABLE even for integers with partial defs, not just
complex and vector variables.  To make that transition easier
the patch inverts DECL_GIMPLE_REG_P to DECL_NOT_GIMPLE_REG_P
since that makes the default the current state for all other
types besides complex and vectors.  That also nicely simplifies
code throughout the compiler.

TREE_ADDRESSABLE and DECL_NOT_GIMPLE_REG_P are now truly
independent, either set prevents a decl from being rewritten
into SSA form.

For the testcase in PR94703 we're able to expand the partial
def'ed local integer to a register then, producing a single
movl rather than going through the stack.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

If there are no objections I'm going to install this once
stage1 opens.

Thanks,
Richard.

2020-04-22  Richard Biener  <rguenther@suse.de>

	PR middle-end/94703
	* tree-core.h (tree_decl_common::gimple_reg_flag): Rename ...
	(tree_decl_common::not_gimple_reg_flag): ... to this.
	* tree.h (DECL_GIMPLE_REG_P): Rename ...
	(DECL_NOT_GIMPLE_REG_P): ... to this.
	* gimple-expr.c (copy_var_decl): Copy DECL_NOT_GIMPLE_REG_P.
	(create_tmp_reg): Simplify.
	(create_tmp_reg_fn): Likewise.
	(is_gimple_reg): Check DECL_NOT_GIMPLE_REG_P for all regs.
	* gimplify.c (create_tmp_from_val): Simplify.
	(gimplify_bind_expr): Likewise.
	(gimplify_compound_literal_expr): Likewise.
	(gimplify_function_tree): Likewise.
	(prepare_gimple_addressable): Set DECL_NOT_GIMPLE_REG_P.
	* asan.c (create_odr_indicator): Do not clear DECL_GIMPLE_REG_P.
	(asan_add_global): Copy it.
	* cgraphunit.c (cgraph_node::expand_thunk): Force args
	to be GIMPLE regs.
	* function.c (gimplify_parameters): Copy
	DECL_NOT_GIMPLE_REG_P.
	* ipa-param-manipulation.c
	(ipa_param_body_adjustments::common_initialization): Simplify.
	(ipa_param_body_adjustments::reset_debug_stmts): Copy
	DECL_NOT_GIMPLE_REG_P.
	* omp-low.c (lower_omp_for_scan): Do not set DECL_GIMPLE_REG_P.
	* sanopt.c (sanitize_rewrite_addressable_params): Likewise.
	* tree-cfg.c (make_blocks_1): Simplify.
	(verify_address): Do not verify DECL_GIMPLE_REG_P setting.
	* tree-eh.c (lower_eh_constructs_2): Simplify.
	* tree-inline.c (declare_return_variable): Adjust and
	generalize.
	(copy_decl_to_var): Copy DECL_NOT_GIMPLE_REG_P.
	(copy_result_decl_to_var): Likewise.
	* tree-into-ssa.c (pass_build_ssa::execute): Adjust comment.
	* tree-nested.c (create_tmp_var_for): Simplify.
	* tree-parloops.c (separate_decls_in_region_name): Copy
	DECL_NOT_GIMPLE_REG_P.
	* tree-sra.c (create_access_replacement): Adjust and
	generalize partial def support.
	* tree-ssa-forwprop.c (pass_forwprop::execute): Set
	DECL_NOT_GIMPLE_REG_P on decls we introduce partial defs on.
	* tree-ssa.c (maybe_optimize_var): Handle clearing of
	TREE_ADDRESSABLE and setting/clearing DECL_NOT_GIMPLE_REG_P
	independently.
	* lto-streamer-out.c (hash_tree): Hash DECL_NOT_GIMPLE_REG_P.
	* tree-streamer-out.c (pack_ts_decl_common_value_fields): Stream
	DECL_NOT_GIMPLE_REG_P.
	* tree-streamer-in.c (unpack_ts_decl_common_value_fields): Likewise.

	lto/
	* lto-common.c (compare_tree_sccs_1): Compare
	DECL_NOT_GIMPLE_REG_P.

	c/
	* gimple-parser.c (c_parser_parse_ssa_name): Do not set
	DECL_GIMPLE_REG_P.

	cp/
	* optimize.c (update_cloned_parm): Copy DECL_NOT_GIMPLE_REG_P.

	* gcc.dg/tree-ssa/pr94703.c: New testcase.
---
 gcc/asan.c                              |  3 +-
 gcc/c/gimple-parser.c                   |  3 --
 gcc/cgraphunit.c                        |  5 +--
 gcc/cp/optimize.c                       |  2 +-
 gcc/function.c                          |  5 +--
 gcc/gimple-expr.c                       | 24 +++---------
 gcc/gimplify.c                          | 46 +----------------------
 gcc/ipa-param-manipulation.c            |  6 +--
 gcc/lto-streamer-out.c                  |  2 +-
 gcc/lto/lto-common.c                    |  2 +-
 gcc/omp-low.c                           |  1 -
 gcc/sanopt.c                            |  1 -
 gcc/testsuite/gcc.dg/tree-ssa/pr94703.c | 11 ++++++
 gcc/tree-cfg.c                          |  9 -----
 gcc/tree-core.h                         |  2 +-
 gcc/tree-eh.c                           |  3 --
 gcc/tree-inline.c                       | 23 ++++--------
 gcc/tree-into-ssa.c                     |  3 +-
 gcc/tree-nested.c                       |  3 --
 gcc/tree-parloops.c                     |  2 +-
 gcc/tree-sra.c                          | 12 ++----
 gcc/tree-ssa-forwprop.c                 |  6 ++-
 gcc/tree-ssa.c                          | 66 +++++++++++++++++----------------
 gcc/tree-streamer-in.c                  |  2 +-
 gcc/tree-streamer-out.c                 |  2 +-
 gcc/tree.h                              |  4 +-
 26 files changed, 84 insertions(+), 164 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94703.c

Comments

Richard Biener April 22, 2020, 1:54 p.m. UTC | #1
On Wed, 22 Apr 2020, Richard Biener wrote:

> 
> This extends DECL_GIMPLE_REG_P to all types so we can clear
> TREE_ADDRESSABLE even for integers with partial defs, not just
> complex and vector variables.  To make that transition easier
> the patch inverts DECL_GIMPLE_REG_P to DECL_NOT_GIMPLE_REG_P
> since that makes the default the current state for all other
> types besides complex and vectors.  That also nicely simplifies
> code throughout the compiler.
> 
> TREE_ADDRESSABLE and DECL_NOT_GIMPLE_REG_P are now truly
> independent, either set prevents a decl from being rewritten
> into SSA form.
> 
> For the testcase in PR94703 we're able to expand the partial
> def'ed local integer to a register then, producing a single
> movl rather than going through the stack.
> 
> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
> 
> If there are no objections I'm going to install this once
> stage1 opens.

Of course there was some fallout.  On 32bit x86 gcc.dg/torture/pr71522.c
fails execution because while the GIMPLE is unchanged at RTL expansion
time:

main ()
{
  char s[12];
  long double d;

  MEM <unsigned char[12]> [(char * {ref-all})&d] = MEM <unsigned char[12]> 
[(char * {ref-all})"AAAAAAAAAAA"];
  MEM <unsigned char[12]> [(char * {ref-all})&s] = MEM <unsigned char[12]> 
[(char * {ref-all})&d];
  _1 = __builtin_strcmp (&s, "AAAAAAAAAAA");
  if (_1 != 0)
...

we now assign 'd' an XFmode register (TREE_ADDRESSABLE is cleared
now since we can set DECL_NOT_GIMPLE_REG_P).  The case is lost
then, impossible to fix up AFAICS.  On x86 all moves to/from
XFmode are normalizing, specifically we end up with

        fldt    .LC0
        fstpt   (%esp)

now the most appealing solution - and totally in the opposite
direction of this patch - is to simply stop expanding non-SSA names
as pseudos.  I do not remember the history as why we do this
but it's likely remanents we preserved from either pre-SSA, times
we did not go into SSA for -O0 or times we really gone out-of-SSA.

There is _some_ good reason to expand a non-SSA "register" into
a pseudo though - namely that RTL is not SSA and thus can accept
partial defs.  And of course that RTL cannot get rid of a stack
slot assigned to a variable.  Today we have somewhat robust
infrastructure to deal with partial defs on GIMPLE, namely
BIT_INSERT_EXPR, but it's not fully exercised.

It's of course possible to fixup the above problematical
cases (there's precenent with discover_nonconstant_array_refs,
which could be "easily" extended to handle "weird" accesses
of non-integral-mode variables) but with the recent discussion
on making RTL expansion more straight-forward I'd bring up
the above idea ... it would get rid of quite some special
code dealing with tcc_reference trees (and MEM_REFs) ending
up operating on registers.

Thanks,
Richard.
Richard Sandiford April 22, 2020, 3:51 p.m. UTC | #2
Richard Biener <rguenther@suse.de> writes:
> On Wed, 22 Apr 2020, Richard Biener wrote:
>
>> 
>> This extends DECL_GIMPLE_REG_P to all types so we can clear
>> TREE_ADDRESSABLE even for integers with partial defs, not just
>> complex and vector variables.  To make that transition easier
>> the patch inverts DECL_GIMPLE_REG_P to DECL_NOT_GIMPLE_REG_P
>> since that makes the default the current state for all other
>> types besides complex and vectors.  That also nicely simplifies
>> code throughout the compiler.
>> 
>> TREE_ADDRESSABLE and DECL_NOT_GIMPLE_REG_P are now truly
>> independent, either set prevents a decl from being rewritten
>> into SSA form.
>> 
>> For the testcase in PR94703 we're able to expand the partial
>> def'ed local integer to a register then, producing a single
>> movl rather than going through the stack.
>> 
>> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
>> 
>> If there are no objections I'm going to install this once
>> stage1 opens.
>
> Of course there was some fallout.  On 32bit x86 gcc.dg/torture/pr71522.c
> fails execution because while the GIMPLE is unchanged at RTL expansion
> time:
>
> main ()
> {
>   char s[12];
>   long double d;
>
>   MEM <unsigned char[12]> [(char * {ref-all})&d] = MEM <unsigned char[12]> 
> [(char * {ref-all})"AAAAAAAAAAA"];
>   MEM <unsigned char[12]> [(char * {ref-all})&s] = MEM <unsigned char[12]> 
> [(char * {ref-all})&d];
>   _1 = __builtin_strcmp (&s, "AAAAAAAAAAA");
>   if (_1 != 0)
> ...
>
> we now assign 'd' an XFmode register (TREE_ADDRESSABLE is cleared
> now since we can set DECL_NOT_GIMPLE_REG_P).  The case is lost
> then, impossible to fix up AFAICS.  On x86 all moves to/from
> XFmode are normalizing, specifically we end up with
>
>         fldt    .LC0
>         fstpt   (%esp)
>
> now the most appealing solution - and totally in the opposite
> direction of this patch - is to simply stop expanding non-SSA names
> as pseudos.  I do not remember the history as why we do this
> but it's likely remanents we preserved from either pre-SSA, times
> we did not go into SSA for -O0 or times we really gone out-of-SSA.
>
> There is _some_ good reason to expand a non-SSA "register" into
> a pseudo though - namely that RTL is not SSA and thus can accept
> partial defs.  And of course that RTL cannot get rid of a stack
> slot assigned to a variable.  Today we have somewhat robust
> infrastructure to deal with partial defs on GIMPLE, namely
> BIT_INSERT_EXPR, but it's not fully exercised.

Yeah, not being able to get rid of the stack slot seems
worrying here.

> It's of course possible to fixup the above problematical
> cases (there's precenent with discover_nonconstant_array_refs,
> which could be "easily" extended to handle "weird" accesses
> of non-integral-mode variables) but with the recent discussion
> on making RTL expansion more straight-forward I'd bring up
> the above idea ... it would get rid of quite some special
> code dealing with tcc_reference trees (and MEM_REFs) ending
> up operating on registers.

It might be nice to do it eventually, but I think at least
is_gimple_reg_type would need to be "return true" first,
otherwise we'll lose too much on aggregates.

There's also the problem that things passed in registers do need
to be RTL registers at function boundaries, so I'm not sure all
the expand code would necessarily go away.

Wouldn't want to see all targets suffer for XFmode oddities :-)

Thanks,
Richard
Richard Biener April 23, 2020, 12:03 p.m. UTC | #3
On Wed, 22 Apr 2020, Richard Sandiford wrote:

> Richard Biener <rguenther@suse.de> writes:
> > On Wed, 22 Apr 2020, Richard Biener wrote:
> >
> >> 
> >> This extends DECL_GIMPLE_REG_P to all types so we can clear
> >> TREE_ADDRESSABLE even for integers with partial defs, not just
> >> complex and vector variables.  To make that transition easier
> >> the patch inverts DECL_GIMPLE_REG_P to DECL_NOT_GIMPLE_REG_P
> >> since that makes the default the current state for all other
> >> types besides complex and vectors.  That also nicely simplifies
> >> code throughout the compiler.
> >> 
> >> TREE_ADDRESSABLE and DECL_NOT_GIMPLE_REG_P are now truly
> >> independent, either set prevents a decl from being rewritten
> >> into SSA form.
> >> 
> >> For the testcase in PR94703 we're able to expand the partial
> >> def'ed local integer to a register then, producing a single
> >> movl rather than going through the stack.
> >> 
> >> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
> >> 
> >> If there are no objections I'm going to install this once
> >> stage1 opens.
> >
> > Of course there was some fallout.  On 32bit x86 gcc.dg/torture/pr71522.c
> > fails execution because while the GIMPLE is unchanged at RTL expansion
> > time:
> >
> > main ()
> > {
> >   char s[12];
> >   long double d;
> >
> >   MEM <unsigned char[12]> [(char * {ref-all})&d] = MEM <unsigned char[12]> 
> > [(char * {ref-all})"AAAAAAAAAAA"];
> >   MEM <unsigned char[12]> [(char * {ref-all})&s] = MEM <unsigned char[12]> 
> > [(char * {ref-all})&d];
> >   _1 = __builtin_strcmp (&s, "AAAAAAAAAAA");
> >   if (_1 != 0)
> > ...
> >
> > we now assign 'd' an XFmode register (TREE_ADDRESSABLE is cleared
> > now since we can set DECL_NOT_GIMPLE_REG_P).  The case is lost
> > then, impossible to fix up AFAICS.  On x86 all moves to/from
> > XFmode are normalizing, specifically we end up with
> >
> >         fldt    .LC0
> >         fstpt   (%esp)
> >
> > now the most appealing solution - and totally in the opposite
> > direction of this patch - is to simply stop expanding non-SSA names
> > as pseudos.  I do not remember the history as why we do this
> > but it's likely remanents we preserved from either pre-SSA, times
> > we did not go into SSA for -O0 or times we really gone out-of-SSA.
> >
> > There is _some_ good reason to expand a non-SSA "register" into
> > a pseudo though - namely that RTL is not SSA and thus can accept
> > partial defs.  And of course that RTL cannot get rid of a stack
> > slot assigned to a variable.  Today we have somewhat robust
> > infrastructure to deal with partial defs on GIMPLE, namely
> > BIT_INSERT_EXPR, but it's not fully exercised.
> 
> Yeah, not being able to get rid of the stack slot seems
> worrying here.
> 
> > It's of course possible to fixup the above problematical
> > cases (there's precenent with discover_nonconstant_array_refs,
> > which could be "easily" extended to handle "weird" accesses
> > of non-integral-mode variables) but with the recent discussion
> > on making RTL expansion more straight-forward I'd bring up
> > the above idea ... it would get rid of quite some special
> > code dealing with tcc_reference trees (and MEM_REFs) ending
> > up operating on registers.
> 
> It might be nice to do it eventually, but I think at least
> is_gimple_reg_type would need to be "return true" first,
> otherwise we'll lose too much on aggregates.
> 
> There's also the problem that things passed in registers do need
> to be RTL registers at function boundaries, so I'm not sure all
> the expand code would necessarily go away.
> 
> Wouldn't want to see all targets suffer for XFmode oddities :-)

OK, so here's the patch amemded with some heuristics to catch
this.  The heuristic triggers exactly on the previously
failing testcase and nothing else on a x86_64 bootstrap and regtest.
Citing the code:

/* If there's a chance to get a pseudo for t then if it would be of float 
mode
   and the actual access is via an integer mode (lowered memcpy or similar
   access) then avoid the register expansion if the mode likely is not 
storage
   suitable for raw bits processing (like XFmode on i?86).  */

static void
avoid_type_punning_on_regs (tree t)
{
  machine_mode access_mode = TYPE_MODE (TREE_TYPE (t));
  if (access_mode != BLKmode
      && !SCALAR_INT_MODE_P (access_mode))
    return;
  tree base = get_base_address (t);
  if (DECL_P (base)
      && !TREE_ADDRESSABLE (base)
      && FLOAT_MODE_P (DECL_MODE (base))
      && maybe_lt (GET_MODE_PRECISION (DECL_MODE (base)),
                   GET_MODE_BITSIZE (GET_MODE_INNER (DECL_MODE (base))))
      /* Double check in the expensive way we really would get a pseudo.  
*/
      && use_register_for_decl (base))
    TREE_ADDRESSABLE (base) = 1;
}

invoked on stores like

            if (gimple_vdef (stmt))
              {
                tree t = gimple_get_lhs (stmt);
                if (t && REFERENCE_CLASS_P (t))
                  avoid_type_punning_on_regs (t);
              }

loads are not an issue on their own.  So the basic idea is to rule
out float-mode pseudos which have less precision than their mode
but where we store to with integer-like modes.  A but hand-wavy
since similar issues might exist with partial integer modes as storage(?),
but we shouldn't really need this at all in an ideal world.

You could check whether this triggers on arm with the respective
long double testcase.

Bootstrapped and tested on x86_64-unknown-linux-gnu, queued for stage1.

Richard.

Subject: [PATCH] extend DECL_GIMPLE_REG_P to all types

This extends DECL_GIMPLE_REG_P to all types so we can clear
TREE_ADDRESSABLE even for integers with partial defs, not just
complex and vector variables.  To make that transition easier
the patch inverts DECL_GIMPLE_REG_P to DECL_NOT_GIMPLE_REG_P
since that makes the default the current state for all other
types besides complex and vectors.

For the testcase in PR94703 we're able to expand the partial
def'ed local integer to a register then, producing a single
movl rather than going through the stack.

On i?86 this execute FAILs gcc.dg/torture/pr71522.c because
we now expand a round-trip through a long double automatic var
to a register fld/fst which normalizes the value.  For that
during RTL expansion we're looking for problematic punnings
of decls and avoid pseudos for those - I chose integer or
BLKmode accesses on decls with modes where precision doesn't
match bitsize which covers the XFmode case.

2020-04-22  Richard Biener  <rguenther@suse.de>

	PR middle-end/94703
	* tree-core.h (tree_decl_common::gimple_reg_flag): Rename ...
	(tree_decl_common::not_gimple_reg_flag): ... to this.
	* tree.h (DECL_GIMPLE_REG_P): Rename ...
	(DECL_NOT_GIMPLE_REG_P): ... to this.
	* gimple-expr.c (copy_var_decl): Copy DECL_NOT_GIMPLE_REG_P.
	(create_tmp_reg): Simplify.
	(create_tmp_reg_fn): Likewise.
	(is_gimple_reg): Check DECL_NOT_GIMPLE_REG_P for all regs.
	* gimplify.c (create_tmp_from_val): Simplify.
	(gimplify_bind_expr): Likewise.
	(gimplify_compound_literal_expr): Likewise.
	(gimplify_function_tree): Likewise.
	(prepare_gimple_addressable): Set DECL_NOT_GIMPLE_REG_P.
	* asan.c (create_odr_indicator): Do not clear DECL_GIMPLE_REG_P.
	(asan_add_global): Copy it.
	* cgraphunit.c (cgraph_node::expand_thunk): Force args
	to be GIMPLE regs.
	* function.c (gimplify_parameters): Copy
	DECL_NOT_GIMPLE_REG_P.
	* ipa-param-manipulation.c
	(ipa_param_body_adjustments::common_initialization): Simplify.
	(ipa_param_body_adjustments::reset_debug_stmts): Copy
	DECL_NOT_GIMPLE_REG_P.
	* omp-low.c (lower_omp_for_scan): Do not set DECL_GIMPLE_REG_P.
	* sanopt.c (sanitize_rewrite_addressable_params): Likewise.
	* tree-cfg.c (make_blocks_1): Simplify.
	(verify_address): Do not verify DECL_GIMPLE_REG_P setting.
	* tree-eh.c (lower_eh_constructs_2): Simplify.
	* tree-inline.c (declare_return_variable): Adjust and
	generalize.
	(copy_decl_to_var): Copy DECL_NOT_GIMPLE_REG_P.
	(copy_result_decl_to_var): Likewise.
	* tree-into-ssa.c (pass_build_ssa::execute): Adjust comment.
	* tree-nested.c (create_tmp_var_for): Simplify.
	* tree-parloops.c (separate_decls_in_region_name): Copy
	DECL_NOT_GIMPLE_REG_P.
	* tree-sra.c (create_access_replacement): Adjust and
	generalize partial def support.
	* tree-ssa-forwprop.c (pass_forwprop::execute): Set
	DECL_NOT_GIMPLE_REG_P on decls we introduce partial defs on.
	* tree-ssa.c (maybe_optimize_var): Handle clearing of
	TREE_ADDRESSABLE and setting/clearing DECL_NOT_GIMPLE_REG_P
	independently.
	* lto-streamer-out.c (hash_tree): Hash DECL_NOT_GIMPLE_REG_P.
	* tree-streamer-out.c (pack_ts_decl_common_value_fields): Stream
	DECL_NOT_GIMPLE_REG_P.
	* tree-streamer-in.c (unpack_ts_decl_common_value_fields): Likewise.
	* cfgexpand.c (avoid_type_punning_on_regs): New.
	(discover_nonconstant_array_refs): Call
	avoid_type_punning_on_regs to avoid unsupported mode punning.

	lto/
	* lto-common.c (compare_tree_sccs_1): Compare
	DECL_NOT_GIMPLE_REG_P.

	c/
	* gimple-parser.c (c_parser_parse_ssa_name): Do not set
	DECL_GIMPLE_REG_P.

	cp/
	* optimize.c (update_cloned_parm): Copy DECL_NOT_GIMPLE_REG_P.

	* gcc.dg/tree-ssa/pr94703.c: New testcase.
---
 gcc/asan.c                              |  3 +-
 gcc/c/gimple-parser.c                   |  3 --
 gcc/cfgexpand.c                         | 29 +++++++++++++++
 gcc/cgraphunit.c                        |  5 +--
 gcc/cp/optimize.c                       |  2 +-
 gcc/function.c                          |  5 +--
 gcc/gimple-expr.c                       | 24 +++---------
 gcc/gimplify.c                          | 46 +----------------------
 gcc/ipa-param-manipulation.c            |  6 +--
 gcc/lto-streamer-out.c                  |  2 +-
 gcc/lto/lto-common.c                    |  2 +-
 gcc/omp-low.c                           |  1 -
 gcc/sanopt.c                            |  1 -
 gcc/testsuite/gcc.dg/tree-ssa/pr94703.c | 11 ++++++
 gcc/tree-cfg.c                          |  9 -----
 gcc/tree-core.h                         |  2 +-
 gcc/tree-eh.c                           |  3 --
 gcc/tree-inline.c                       | 28 +++++++-------
 gcc/tree-into-ssa.c                     |  3 +-
 gcc/tree-nested.c                       |  3 --
 gcc/tree-parloops.c                     |  2 +-
 gcc/tree-sra.c                          | 12 ++----
 gcc/tree-ssa-forwprop.c                 |  6 ++-
 gcc/tree-ssa.c                          | 66 +++++++++++++++++----------------
 gcc/tree-streamer-in.c                  |  2 +-
 gcc/tree-streamer-out.c                 |  2 +-
 gcc/tree.h                              |  4 +-
 27 files changed, 118 insertions(+), 164 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94703.c

diff --git a/gcc/asan.c b/gcc/asan.c
index ae14f7e543c..c9872f1b007 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -2696,7 +2696,6 @@ create_odr_indicator (tree decl, tree type)
   TREE_ADDRESSABLE (var) = 1;
   TREE_READONLY (var) = 0;
   TREE_THIS_VOLATILE (var) = 1;
-  DECL_GIMPLE_REG_P (var) = 0;
   DECL_ARTIFICIAL (var) = 1;
   DECL_IGNORED_P (var) = 1;
   TREE_STATIC (var) = 1;
@@ -2766,7 +2765,7 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
       TREE_ADDRESSABLE (refdecl) = TREE_ADDRESSABLE (decl);
       TREE_READONLY (refdecl) = TREE_READONLY (decl);
       TREE_THIS_VOLATILE (refdecl) = TREE_THIS_VOLATILE (decl);
-      DECL_GIMPLE_REG_P (refdecl) = DECL_GIMPLE_REG_P (decl);
+      DECL_NOT_GIMPLE_REG_P (refdecl) = DECL_NOT_GIMPLE_REG_P (decl);
       DECL_ARTIFICIAL (refdecl) = DECL_ARTIFICIAL (decl);
       DECL_IGNORED_P (refdecl) = DECL_IGNORED_P (decl);
       TREE_STATIC (refdecl) = 1;
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 4e8ff5b1c4f..577d8b58c7d 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -1272,9 +1272,6 @@ c_parser_parse_ssa_name (gimple_parser &parser,
 	      error ("invalid base %qE for SSA name", parent);
 	      return error_mark_node;
 	    }
-	  if (VECTOR_TYPE_P (TREE_TYPE (parent))
-	      || TREE_CODE (TREE_TYPE (parent)) == COMPLEX_TYPE)
-	    DECL_GIMPLE_REG_P (parent) = 1;
 	  name = make_ssa_name_fn (cfun, parent,
 				   gimple_build_nop (), version);
 	}
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index a7ec77d5c85..2d39c5e43c5 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -6126,6 +6126,29 @@ discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
   return NULL_TREE;
 }
 
+/* If there's a chance to get a pseudo for t then if it would be of float mode
+   and the actual access is via an integer mode (lowered memcpy or similar
+   access) then avoid the register expansion if the mode likely is not storage
+   suitable for raw bits processing (like XFmode on i?86).  */
+
+static void
+avoid_type_punning_on_regs (tree t)
+{
+  machine_mode access_mode = TYPE_MODE (TREE_TYPE (t));
+  if (access_mode != BLKmode
+      && !SCALAR_INT_MODE_P (access_mode))
+    return;
+  tree base = get_base_address (t);
+  if (DECL_P (base)
+      && !TREE_ADDRESSABLE (base)
+      && FLOAT_MODE_P (DECL_MODE (base))
+      && maybe_lt (GET_MODE_PRECISION (DECL_MODE (base)),
+		   GET_MODE_BITSIZE (GET_MODE_INNER (DECL_MODE (base))))
+      /* Double check in the expensive way we really would get a pseudo.  */
+      && use_register_for_decl (base))
+    TREE_ADDRESSABLE (base) = 1;
+}
+
 /* RTL expansion is not able to compile array references with variable
    offsets for arrays stored in single register.  Discover such
    expressions and mark variables as addressable to avoid this
@@ -6159,6 +6182,12 @@ discover_nonconstant_array_refs (void)
 		default:
 		  break;
 		}
+	    if (gimple_vdef (stmt))
+	      {
+		tree t = gimple_get_lhs (stmt);
+		if (t && REFERENCE_CLASS_P (t))
+		  avoid_type_punning_on_regs (t);
+	      }
 	  }
       }
 }
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index a1ace95879a..0563932a709 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2058,10 +2058,7 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
 	for (; i < nargs; i++, arg = DECL_CHAIN (arg))
 	  {
 	    tree tmp = arg;
-	    if (VECTOR_TYPE_P (TREE_TYPE (arg))
-		|| TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-	      DECL_GIMPLE_REG_P (arg) = 1;
-
+	    DECL_NOT_GIMPLE_REG_P (arg) = 0;
 	    if (!is_gimple_val (arg))
 	      {
 		tmp = create_tmp_reg (TYPE_MAIN_VARIANT
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index d4f12dbb84d..abdcd7fa19f 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -58,7 +58,7 @@ update_cloned_parm (tree parm, tree cloned_parm, bool first)
   DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
   TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
 
-  DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm);
+  DECL_NOT_GIMPLE_REG_P (cloned_parm) = DECL_NOT_GIMPLE_REG_P (parm);
 }
 
 /* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
diff --git a/gcc/function.c b/gcc/function.c
index d616f5f64f4..9eee9b59bfd 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -3913,9 +3913,8 @@ gimplify_parameters (gimple_seq *cleanup)
 		     as we'll query that flag during gimplification.  */
 		  if (TREE_ADDRESSABLE (parm))
 		    TREE_ADDRESSABLE (local) = 1;
-		  else if (TREE_CODE (type) == COMPLEX_TYPE
-			   || TREE_CODE (type) == VECTOR_TYPE)
-		    DECL_GIMPLE_REG_P (local) = 1;
+		  if (DECL_NOT_GIMPLE_REG_P (parm))
+		    DECL_NOT_GIMPLE_REG_P (local) = 1;
 
 		  if (!is_gimple_reg (local)
 		      && flag_stack_reuse != SR_NONE)
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index 44a0b8790f5..45871ac2c27 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -373,7 +373,7 @@ copy_var_decl (tree var, tree name, tree type)
 
   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
-  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
+  DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (var);
   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
   DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
   DECL_CONTEXT (copy) = DECL_CONTEXT (var);
@@ -493,14 +493,7 @@ create_tmp_var (tree type, const char *prefix)
 tree
 create_tmp_reg (tree type, const char *prefix)
 {
-  tree tmp;
-
-  tmp = create_tmp_var (type, prefix);
-  if (TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (tmp) = 1;
-
-  return tmp;
+  return create_tmp_var (type, prefix);
 }
 
 /* Create a new temporary variable declaration of type TYPE by calling
@@ -514,9 +507,6 @@ create_tmp_reg_fn (struct function *fn, tree type, const char *prefix)
 
   tmp = create_tmp_var_raw (type, prefix);
   gimple_add_tmp_var_fn (fn, tmp);
-  if (TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (tmp) = 1;
 
   return tmp;
 }
@@ -792,13 +782,9 @@ is_gimple_reg (tree t)
   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
     return false;
 
-  /* Complex and vector values must have been put into SSA-like form.
-     That is, no assignments to the individual components.  */
-  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-    return DECL_GIMPLE_REG_P (t);
-
-  return true;
+  /* Variables can be marked as having partial definitions, avoid
+     putting them into SSA form.  */
+  return !DECL_NOT_GIMPLE_REG_P (t);
 }
 
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 2f2c51b2d89..ef7679d4c2b 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -559,9 +559,6 @@ create_tmp_from_val (tree val)
   /* Drop all qualifiers and address-space information from the value type.  */
   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
   tree var = create_tmp_var (type, get_name (val));
-  if (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (var) = 1;
   return var;
 }
 
@@ -1400,16 +1397,6 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
 	  if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
 	    cfun->has_local_explicit_reg_vars = true;
 	}
-
-      /* Preliminarily mark non-addressed complex variables as eligible
-	 for promotion to gimple registers.  We'll transform their uses
-	 as we find them.  */
-      if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-	   || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-	  && !TREE_THIS_VOLATILE (t)
-	  && (VAR_P (t) && !DECL_HARD_REGISTER (t))
-	  && !needs_to_live_in_memory (t))
-	DECL_GIMPLE_REG_P (t) = 1;
     }
 
   bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
@@ -4308,7 +4295,7 @@ prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
     {
       /* Do not allow an SSA name as the temporary.  */
       tree var = get_initialized_tmp_var (*expr_p, seq_p, NULL, false);
-      DECL_GIMPLE_REG_P (var) = 0;
+      DECL_NOT_GIMPLE_REG_P (var) = 1;
       *expr_p = var;
     }
 }
@@ -4774,15 +4761,6 @@ gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
       return GS_OK;
     }
 
-  /* Preliminarily mark non-addressed complex variables as eligible
-     for promotion to gimple registers.  We'll transform their uses
-     as we find them.  */
-  if ((TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE
-       || TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE)
-      && !TREE_THIS_VOLATILE (decl)
-      && !needs_to_live_in_memory (decl))
-    DECL_GIMPLE_REG_P (decl) = 1;
-
   /* If the decl is not addressable, then it is being used in some
      expression or on the right hand side of a statement, and it can
      be put into a readonly data section.  */
@@ -5617,8 +5595,7 @@ is_gimple_stmt (tree t)
 
 
 /* Promote partial stores to COMPLEX variables to total stores.  *EXPR_P is
-   a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a variable with
-   DECL_GIMPLE_REG_P set.
+   a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register.
 
    IMPORTANT NOTE: This promotion is performed by introducing a load of the
    other, unmodified part of the complex object just before the total store.
@@ -14992,7 +14969,6 @@ flag_instrument_functions_exclude_p (tree fndecl)
 void
 gimplify_function_tree (tree fndecl)
 {
-  tree parm, ret;
   gimple_seq seq;
   gbind *bind;
 
@@ -15007,24 +14983,6 @@ gimplify_function_tree (tree fndecl)
      if necessary.  */
   cfun->curr_properties |= PROP_gimple_lva;
 
-  for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = DECL_CHAIN (parm))
-    {
-      /* Preliminarily mark non-addressed complex variables as eligible
-         for promotion to gimple registers.  We'll transform their uses
-         as we find them.  */
-      if ((TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE
-	   || TREE_CODE (TREE_TYPE (parm)) == VECTOR_TYPE)
-          && !TREE_THIS_VOLATILE (parm)
-          && !needs_to_live_in_memory (parm))
-        DECL_GIMPLE_REG_P (parm) = 1;
-    }
-
-  ret = DECL_RESULT (fndecl);
-  if ((TREE_CODE (TREE_TYPE (ret)) == COMPLEX_TYPE
-       || TREE_CODE (TREE_TYPE (ret)) == VECTOR_TYPE)
-      && !needs_to_live_in_memory (ret))
-    DECL_GIMPLE_REG_P (ret) = 1;
-
   if (asan_sanitize_use_after_scope () && sanitize_flags_p (SANITIZE_ADDRESS))
     asan_poisoned_variables = new hash_set<tree> ();
   bind = gimplify_body (fndecl, true);
diff --git a/gcc/ipa-param-manipulation.c b/gcc/ipa-param-manipulation.c
index 839bd2ef870..978916057f0 100644
--- a/gcc/ipa-param-manipulation.c
+++ b/gcc/ipa-param-manipulation.c
@@ -1028,10 +1028,6 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl,
 	  DECL_CONTEXT (new_parm) = m_fndecl;
 	  TREE_USED (new_parm) = 1;
 	  DECL_IGNORED_P (new_parm) = 1;
-	  /* We assume all newly created arguments are not addressable.  */
-	  if (TREE_CODE (new_type) == COMPLEX_TYPE
-	      || TREE_CODE (new_type) == VECTOR_TYPE)
-	    DECL_GIMPLE_REG_P (new_parm) = 1;
 	  layout_decl (new_parm, 0);
 	  m_new_decls.quick_push (new_parm);
 
@@ -1888,7 +1884,7 @@ ipa_param_body_adjustments::reset_debug_stmts ()
 	  TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
 	  TREE_READONLY (copy) = TREE_READONLY (decl);
 	  TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
-	  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
+	  DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
 	  DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl);
 	  DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl);
 	  DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 52ef94718db..c5edb6b00fd 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -1067,7 +1067,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
       hstate.add_flag (DECL_USER_ALIGN (t));
       hstate.add_flag (DECL_PRESERVE_P (t));
       hstate.add_flag (DECL_EXTERNAL (t));
-      hstate.add_flag (DECL_GIMPLE_REG_P (t));
+      hstate.add_flag (DECL_NOT_GIMPLE_REG_P (t));
       hstate.commit_flag ();
       hstate.add_int (DECL_ALIGN (t));
       if (code == LABEL_DECL)
diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index cee5f0e9935..afd2375c516 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -1167,7 +1167,7 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
       compare_values (DECL_USER_ALIGN);
       compare_values (DECL_PRESERVE_P);
       compare_values (DECL_EXTERNAL);
-      compare_values (DECL_GIMPLE_REG_P);
+      compare_values (DECL_NOT_GIMPLE_REG_P);
       compare_values (DECL_ALIGN);
       if (code == LABEL_DECL)
 	{
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 88f23e60d34..c8c9db43afb 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -10322,7 +10322,6 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt,
   gimple_seq_add_stmt (body_p, g);
 
   tree cplx = create_tmp_var (build_complex_type (unsigned_type_node, false));
-  DECL_GIMPLE_REG_P (cplx) = 1;
   g = gimple_build_call_internal (IFN_MUL_OVERFLOW, 2, thread_nump1, twok);
   gimple_call_set_lhs (g, cplx);
   gimple_seq_add_stmt (body_p, g);
diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 0788eef597e..86180e32c7e 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -1189,7 +1189,6 @@ sanitize_rewrite_addressable_params (function *fun)
 	    {
 	      /* We need to create a SSA name that will be used for the
 		 assignment.  */
-	      DECL_GIMPLE_REG_P (arg) = 1;
 	      tree tmp = get_or_create_ssa_default_def (cfun, arg);
 	      g = gimple_build_assign (var, tmp);
 	      gimple_set_location (g, DECL_SOURCE_LOCATION (arg));
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94703.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94703.c
new file mode 100644
index 00000000000..7209fa0a4d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94703.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-ssa" } */
+
+unsigned int set_lowpart (unsigned int const *X)
+{
+  unsigned int r = 0;
+  __builtin_memcpy(&r,X,sizeof (unsigned int) / 2);
+  return r;
+}
+
+/* { dg-final { scan-tree-dump "No longer having address taken: r" "ssa" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index e99fb9ff5d1..8b6548f3001 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -577,9 +577,6 @@ make_blocks_1 (gimple_seq seq, basic_block bb)
 	      gimple_set_location (s, gimple_location (stmt));
 	      gimple_set_block (s, gimple_block (stmt));
 	      gimple_set_lhs (stmt, tmp);
-	      if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
-		  || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
-		DECL_GIMPLE_REG_P (tmp) = 1;
 	      gsi_insert_after (&i, s, GSI_SAME_STMT);
 	    }
 	  start_new_block = true;
@@ -2983,12 +2980,6 @@ verify_address (tree t, bool verify_addressable)
 	|| TREE_CODE (base) == RESULT_DECL))
     return false;
 
-  if (DECL_GIMPLE_REG_P (base))
-    {
-      error ("%<DECL_GIMPLE_REG_P%> set on a variable with address taken");
-      return true;
-    }
-
   if (verify_addressable && !TREE_ADDRESSABLE (base))
     {
       error ("address taken but %<TREE_ADDRESSABLE%> bit not set");
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index d84fe959acc..9439f1ffc88 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1723,7 +1723,7 @@ struct GTY(()) tree_decl_common {
   unsigned decl_flag_3 : 1;
   /* Logically, these two would go in a theoretical base shared by var and
      parm decl. */
-  unsigned gimple_reg_flag : 1;
+  unsigned not_gimple_reg_flag : 1;
   /* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_BY_REFERENCE.  */
   unsigned decl_by_reference_flag : 1;
   /* In a VAR_DECL and PARM_DECL, this is DECL_READ_P.  */
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 2a409dcaffe..10ef2e3157c 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2072,9 +2072,6 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
 	  gimple_set_location (s, gimple_location (stmt));
 	  gimple_set_block (s, gimple_block (stmt));
 	  gimple_set_lhs (stmt, tmp);
-	  if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
-	      || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
-	    DECL_GIMPLE_REG_P (tmp) = 1;
 	  gsi_insert_after (gsi, s, GSI_SAME_STMT);
 	}
       /* Look for things that can throw exceptions, and record them.  */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 69ca8e99109..80f35ef9350 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3670,11 +3670,9 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 	  if (TREE_ADDRESSABLE (result))
 	    mark_addressable (var);
 	}
-      if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
-           || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE)
-	  && !DECL_GIMPLE_REG_P (result)
+      if (DECL_NOT_GIMPLE_REG_P (result)
 	  && DECL_P (var))
-	DECL_GIMPLE_REG_P (var) = 0;
+	DECL_NOT_GIMPLE_REG_P (var) = 1;
 
       if (!useless_type_conversion_p (callee_type, caller_type))
 	var = build1 (VIEW_CONVERT_EXPR, callee_type, var);
@@ -3717,10 +3715,8 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 	    use_it = false;
 	  else if (is_global_var (base_m))
 	    use_it = false;
-	  else if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
-		    || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE)
-		   && !DECL_GIMPLE_REG_P (result)
-		   && DECL_GIMPLE_REG_P (base_m))
+	  else if (DECL_NOT_GIMPLE_REG_P (result)
+		   && !DECL_NOT_GIMPLE_REG_P (base_m))
 	    use_it = false;
 	  else if (!TREE_ADDRESSABLE (base_m))
 	    use_it = true;
@@ -3760,11 +3756,8 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 	     to using a MEM_REF to not leak invalid GIMPLE to the following
 	     passes.  */
 	  /* Prevent var from being written into SSA form.  */
-	  if (TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
-	      || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE)
-	    DECL_GIMPLE_REG_P (var) = false;
-	  else if (is_gimple_reg_type (TREE_TYPE (var)))
-	    TREE_ADDRESSABLE (var) = true;
+	  if (is_gimple_reg_type (TREE_TYPE (var)))
+	    DECL_NOT_GIMPLE_REG_P (var) = true;
 	  use = fold_build2 (MEM_REF, caller_type,
 			     build_fold_addr_expr (var),
 			     build_int_cst (ptr_type_node, 0));
@@ -5930,7 +5923,7 @@ copy_decl_to_var (tree decl, copy_body_data *id)
   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
   TREE_READONLY (copy) = TREE_READONLY (decl);
   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
-  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
+  DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
   DECL_BY_REFERENCE (copy) = DECL_BY_REFERENCE (decl);
 
   return copy_decl_for_dup_finish (id, decl, copy);
@@ -5960,7 +5953,12 @@ copy_result_decl_to_var (tree decl, copy_body_data *id)
   if (!DECL_BY_REFERENCE (decl))
     {
       TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
-      DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
+      DECL_NOT_GIMPLE_REG_P (copy)
+	= (DECL_NOT_GIMPLE_REG_P (decl)
+	   /* RESULT_DECLs are treated special by needs_to_live_in_memory,
+	      mirror that to the created VAR_DECL.  */
+	   || (TREE_CODE (decl) == RESULT_DECL
+	       && aggregate_value_p (decl, id->src_fn)));
     }
 
   return copy_decl_for_dup_finish (id, decl, copy);
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 6528acac31a..c24931effac 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -2430,8 +2430,7 @@ pass_build_ssa::execute (function *fun)
   basic_block bb;
 
   /* Increase the set of variables we can rewrite into SSA form
-     by clearing TREE_ADDRESSABLE and setting DECL_GIMPLE_REG_P
-     and transform the IL to support this.  */
+     by clearing TREE_ADDRESSABLE and transform the IL to support this.  */
   if (optimize)
     execute_update_addresses_taken ();
 
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 6f696da5332..de168df70a1 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -160,9 +160,6 @@ create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
   DECL_CONTEXT (tmp_var) = info->context;
   DECL_CHAIN (tmp_var) = info->new_local_var_chain;
   DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
-  if (TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (tmp_var) = 1;
 
   info->new_local_var_chain = tmp_var;
 
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index d9250d36c72..8cd50234a1c 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1574,7 +1574,7 @@ separate_decls_in_region_name (tree name, name_to_copy_table_type *name_copies,
   if (!dslot->to)
     {
       var_copy = create_tmp_var (TREE_TYPE (var), get_name (var));
-      DECL_GIMPLE_REG_P (var_copy) = DECL_GIMPLE_REG_P (var);
+      DECL_NOT_GIMPLE_REG_P (var_copy) = DECL_NOT_GIMPLE_REG_P (var);
       dslot->uid = uid;
       dslot->to = var_copy;
 
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 227bde06257..4793b48f32c 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -2168,15 +2168,9 @@ create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
        variant.  This avoids issues with weirdo ABIs like AAPCS.  */
     repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT (type),
 						 TYPE_QUALS (type)), "SR");
-  if (TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    {
-      if (!access->grp_partial_lhs)
-	DECL_GIMPLE_REG_P (repl) = 1;
-    }
-  else if (access->grp_partial_lhs
-	   && is_gimple_reg_type (type))
-    TREE_ADDRESSABLE (repl) = 1;
+  if (access->grp_partial_lhs
+      && is_gimple_reg_type (type))
+    DECL_NOT_GIMPLE_REG_P (repl) = 1;
 
   DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
   DECL_ARTIFICIAL (repl) = 1;
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 1a50045b367..b68da91723b 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2945,6 +2945,8 @@ pass_forwprop::execute (function *fun)
 		      != TARGET_MEM_REF))
 		{
 		  tree use_lhs = gimple_assign_lhs (use_stmt);
+		  if (auto_var_p (use_lhs))
+		    DECL_NOT_GIMPLE_REG_P (use_lhs) = 1;
 		  tree new_lhs = build1 (REALPART_EXPR,
 					 TREE_TYPE (TREE_TYPE (use_lhs)),
 					 unshare_expr (use_lhs));
@@ -2996,6 +2998,9 @@ pass_forwprop::execute (function *fun)
 		    = tree_to_uhwi (TYPE_SIZE (elt_t));
 		  unsigned HOST_WIDE_INT n
 		    = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs)));
+		  tree use_lhs = gimple_assign_lhs (use_stmt);
+		  if (auto_var_p (use_lhs))
+		    DECL_NOT_GIMPLE_REG_P (use_lhs) = 1;
 		  for (unsigned HOST_WIDE_INT bi = 0; bi < n; bi += elt_w)
 		    {
 		      unsigned HOST_WIDE_INT ci = bi / elt_w;
@@ -3004,7 +3009,6 @@ pass_forwprop::execute (function *fun)
 			new_rhs = CONSTRUCTOR_ELT (rhs, ci)->value;
 		      else
 			new_rhs = build_zero_cst (elt_t);
-		      tree use_lhs = gimple_assign_lhs (use_stmt);
 		      tree new_lhs = build3 (BIT_FIELD_REF,
 					     elt_t,
 					     unshare_expr (use_lhs),
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 4f4ab2b8992..c47b963bbb2 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1583,8 +1583,8 @@ non_rewritable_lvalue_p (tree lhs)
   return true;
 }
 
-/* When possible, clear TREE_ADDRESSABLE bit or set DECL_GIMPLE_REG_P bit and
-   mark the variable VAR for conversion into SSA.  Return true when updating
+/* When possible, clear TREE_ADDRESSABLE bit, set or clear DECL_NOT_GIMPLE_REG_P
+   and mark the variable VAR for conversion into SSA.  Return true when updating
    stmts is required.  */
 
 static void
@@ -1597,24 +1597,11 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs,
       || bitmap_bit_p (addresses_taken, DECL_UID (var)))
     return;
 
-  if (TREE_ADDRESSABLE (var)
-      /* Do not change TREE_ADDRESSABLE if we need to preserve var as
-	 a non-register.  Otherwise we are confused and forget to
-	 add virtual operands for it.  */
-      && (!is_gimple_reg_type (TREE_TYPE (var))
-	  || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
-	  || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
-	  || !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
+  bool maybe_reg = false;
+  if (TREE_ADDRESSABLE (var))
     {
       TREE_ADDRESSABLE (var) = 0;
-      /* If we cleared TREE_ADDRESSABLE make sure DECL_GIMPLE_REG_P
-         is unset if we cannot rewrite the var into SSA.  */
-      if ((TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
-	   || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE)
-	  && bitmap_bit_p (not_reg_needs, DECL_UID (var)))
-	DECL_GIMPLE_REG_P (var) = 0;
-      if (is_gimple_reg (var))
-	bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
+      maybe_reg = true;
       if (dump_file)
 	{
 	  fprintf (dump_file, "No longer having address taken: ");
@@ -1623,20 +1610,36 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs,
 	}
     }
 
-  if (!DECL_GIMPLE_REG_P (var)
-      && !bitmap_bit_p (not_reg_needs, DECL_UID (var))
-      && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
-	  || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE)
-      && !TREE_THIS_VOLATILE (var)
-      && (!VAR_P (var) || !DECL_HARD_REGISTER (var)))
+  /* For register type decls if we do not have any partial defs
+     we cannot express in SSA form mark them as DECL_NOT_GIMPLE_REG_P
+     as to avoid SSA rewrite.  For the others go ahead and mark
+     them for renaming.  */
+  if (is_gimple_reg_type (TREE_TYPE (var)))
     {
-      DECL_GIMPLE_REG_P (var) = 1;
-      bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
-      if (dump_file)
+      if (bitmap_bit_p (not_reg_needs, DECL_UID (var)))
 	{
-	  fprintf (dump_file, "Now a gimple register: ");
-	  print_generic_expr (dump_file, var);
-	  fprintf (dump_file, "\n");
+	  DECL_NOT_GIMPLE_REG_P (var) = 1;
+	  if (dump_file)
+	    {
+	      fprintf (dump_file, "Has partial defs: ");
+	      print_generic_expr (dump_file, var);
+	      fprintf (dump_file, "\n");
+	    }
+	}
+      else if (DECL_NOT_GIMPLE_REG_P (var))
+	{
+	  maybe_reg = true;
+	  DECL_NOT_GIMPLE_REG_P (var) = 0;
+	}
+      if (maybe_reg && is_gimple_reg (var))
+	{
+	  if (dump_file)
+	    {
+	      fprintf (dump_file, "Now a gimple register: ");
+	      print_generic_expr (dump_file, var);
+	      fprintf (dump_file, "\n");
+	    }
+	  bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
 	}
     }
 }
@@ -1669,7 +1672,8 @@ is_asan_mark_p (gimple *stmt)
   return false;
 }
 
-/* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables.  */
+/* Compute TREE_ADDRESSABLE and whether we have unhandled partial defs
+   for local variables.  */
 
 void
 execute_update_addresses_taken (void)
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 0bfc272d076..79b97ffa9a3 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -236,7 +236,7 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
   DECL_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_PRESERVE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_EXTERNAL (expr) = (unsigned) bp_unpack_value (bp, 1);
-  DECL_GIMPLE_REG_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+  DECL_NOT_GIMPLE_REG_P (expr) = (unsigned) bp_unpack_value (bp, 1);
   SET_DECL_ALIGN (expr, (unsigned) bp_unpack_var_len_unsigned (bp));
 #ifdef ACCEL_COMPILER
   if (DECL_ALIGN (expr) > targetm.absolute_biggest_alignment)
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 5bbcebba87e..3ab8c889a23 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -201,7 +201,7 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
   bp_pack_value (bp, DECL_USER_ALIGN (expr), 1);
   bp_pack_value (bp, DECL_PRESERVE_P (expr), 1);
   bp_pack_value (bp, DECL_EXTERNAL (expr), 1);
-  bp_pack_value (bp, DECL_GIMPLE_REG_P (expr), 1);
+  bp_pack_value (bp, DECL_NOT_GIMPLE_REG_P (expr), 1);
   bp_pack_var_len_unsigned (bp, DECL_ALIGN (expr));
 
   if (TREE_CODE (expr) == LABEL_DECL)
diff --git a/gcc/tree.h b/gcc/tree.h
index 1c28785d411..66042c14290 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2646,8 +2646,8 @@ extern machine_mode vector_type_mode (const_tree);
    they are killing assignments.  Thus the variable may now
    be treated as a GIMPLE register, and use real instead of
    virtual ops in SSA form.  */
-#define DECL_GIMPLE_REG_P(DECL) \
-  DECL_COMMON_CHECK (DECL)->decl_common.gimple_reg_flag
+#define DECL_NOT_GIMPLE_REG_P(DECL) \
+  DECL_COMMON_CHECK (DECL)->decl_common.not_gimple_reg_flag
 
 extern tree decl_value_expr_lookup (tree);
 extern void decl_value_expr_insert (tree, tree);
Richard Biener May 7, 2020, 1:40 p.m. UTC | #4
On Thu, 23 Apr 2020, Richard Biener wrote:

> On Wed, 22 Apr 2020, Richard Sandiford wrote:
> 
> > Richard Biener <rguenther@suse.de> writes:
> > > On Wed, 22 Apr 2020, Richard Biener wrote:
> > >
> > >> 
> > >> This extends DECL_GIMPLE_REG_P to all types so we can clear
> > >> TREE_ADDRESSABLE even for integers with partial defs, not just
> > >> complex and vector variables.  To make that transition easier
> > >> the patch inverts DECL_GIMPLE_REG_P to DECL_NOT_GIMPLE_REG_P
> > >> since that makes the default the current state for all other
> > >> types besides complex and vectors.  That also nicely simplifies
> > >> code throughout the compiler.
> > >> 
> > >> TREE_ADDRESSABLE and DECL_NOT_GIMPLE_REG_P are now truly
> > >> independent, either set prevents a decl from being rewritten
> > >> into SSA form.
> > >> 
> > >> For the testcase in PR94703 we're able to expand the partial
> > >> def'ed local integer to a register then, producing a single
> > >> movl rather than going through the stack.
> > >> 
> > >> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
> > >> 
> > >> If there are no objections I'm going to install this once
> > >> stage1 opens.
> > >
> > > Of course there was some fallout.  On 32bit x86 gcc.dg/torture/pr71522.c
> > > fails execution because while the GIMPLE is unchanged at RTL expansion
> > > time:
> > >
> > > main ()
> > > {
> > >   char s[12];
> > >   long double d;
> > >
> > >   MEM <unsigned char[12]> [(char * {ref-all})&d] = MEM <unsigned char[12]> 
> > > [(char * {ref-all})"AAAAAAAAAAA"];
> > >   MEM <unsigned char[12]> [(char * {ref-all})&s] = MEM <unsigned char[12]> 
> > > [(char * {ref-all})&d];
> > >   _1 = __builtin_strcmp (&s, "AAAAAAAAAAA");
> > >   if (_1 != 0)
> > > ...
> > >
> > > we now assign 'd' an XFmode register (TREE_ADDRESSABLE is cleared
> > > now since we can set DECL_NOT_GIMPLE_REG_P).  The case is lost
> > > then, impossible to fix up AFAICS.  On x86 all moves to/from
> > > XFmode are normalizing, specifically we end up with
> > >
> > >         fldt    .LC0
> > >         fstpt   (%esp)
> > >
> > > now the most appealing solution - and totally in the opposite
> > > direction of this patch - is to simply stop expanding non-SSA names
> > > as pseudos.  I do not remember the history as why we do this
> > > but it's likely remanents we preserved from either pre-SSA, times
> > > we did not go into SSA for -O0 or times we really gone out-of-SSA.
> > >
> > > There is _some_ good reason to expand a non-SSA "register" into
> > > a pseudo though - namely that RTL is not SSA and thus can accept
> > > partial defs.  And of course that RTL cannot get rid of a stack
> > > slot assigned to a variable.  Today we have somewhat robust
> > > infrastructure to deal with partial defs on GIMPLE, namely
> > > BIT_INSERT_EXPR, but it's not fully exercised.
> > 
> > Yeah, not being able to get rid of the stack slot seems
> > worrying here.
> > 
> > > It's of course possible to fixup the above problematical
> > > cases (there's precenent with discover_nonconstant_array_refs,
> > > which could be "easily" extended to handle "weird" accesses
> > > of non-integral-mode variables) but with the recent discussion
> > > on making RTL expansion more straight-forward I'd bring up
> > > the above idea ... it would get rid of quite some special
> > > code dealing with tcc_reference trees (and MEM_REFs) ending
> > > up operating on registers.
> > 
> > It might be nice to do it eventually, but I think at least
> > is_gimple_reg_type would need to be "return true" first,
> > otherwise we'll lose too much on aggregates.
> > 
> > There's also the problem that things passed in registers do need
> > to be RTL registers at function boundaries, so I'm not sure all
> > the expand code would necessarily go away.
> > 
> > Wouldn't want to see all targets suffer for XFmode oddities :-)
> 
> OK, so here's the patch amemded with some heuristics to catch
> this.  The heuristic triggers exactly on the previously
> failing testcase and nothing else on a x86_64 bootstrap and regtest.
> Citing the code:
> 
> /* If there's a chance to get a pseudo for t then if it would be of float 
> mode
>    and the actual access is via an integer mode (lowered memcpy or similar
>    access) then avoid the register expansion if the mode likely is not 
> storage
>    suitable for raw bits processing (like XFmode on i?86).  */
> 
> static void
> avoid_type_punning_on_regs (tree t)
> {
>   machine_mode access_mode = TYPE_MODE (TREE_TYPE (t));
>   if (access_mode != BLKmode
>       && !SCALAR_INT_MODE_P (access_mode))
>     return;
>   tree base = get_base_address (t);
>   if (DECL_P (base)
>       && !TREE_ADDRESSABLE (base)
>       && FLOAT_MODE_P (DECL_MODE (base))
>       && maybe_lt (GET_MODE_PRECISION (DECL_MODE (base)),
>                    GET_MODE_BITSIZE (GET_MODE_INNER (DECL_MODE (base))))
>       /* Double check in the expensive way we really would get a pseudo.  
> */
>       && use_register_for_decl (base))
>     TREE_ADDRESSABLE (base) = 1;
> }
> 
> invoked on stores like
> 
>             if (gimple_vdef (stmt))
>               {
>                 tree t = gimple_get_lhs (stmt);
>                 if (t && REFERENCE_CLASS_P (t))
>                   avoid_type_punning_on_regs (t);
>               }
> 
> loads are not an issue on their own.  So the basic idea is to rule
> out float-mode pseudos which have less precision than their mode
> but where we store to with integer-like modes.  A but hand-wavy
> since similar issues might exist with partial integer modes as storage(?),
> but we shouldn't really need this at all in an ideal world.
> 
> You could check whether this triggers on arm with the respective
> long double testcase.
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu, queued for stage1.

I have now pushed this.

Richard.

> Richard.
> 
> Subject: [PATCH] extend DECL_GIMPLE_REG_P to all types
> 
> This extends DECL_GIMPLE_REG_P to all types so we can clear
> TREE_ADDRESSABLE even for integers with partial defs, not just
> complex and vector variables.  To make that transition easier
> the patch inverts DECL_GIMPLE_REG_P to DECL_NOT_GIMPLE_REG_P
> since that makes the default the current state for all other
> types besides complex and vectors.
> 
> For the testcase in PR94703 we're able to expand the partial
> def'ed local integer to a register then, producing a single
> movl rather than going through the stack.
> 
> On i?86 this execute FAILs gcc.dg/torture/pr71522.c because
> we now expand a round-trip through a long double automatic var
> to a register fld/fst which normalizes the value.  For that
> during RTL expansion we're looking for problematic punnings
> of decls and avoid pseudos for those - I chose integer or
> BLKmode accesses on decls with modes where precision doesn't
> match bitsize which covers the XFmode case.
> 
> 2020-04-22  Richard Biener  <rguenther@suse.de>
> 
> 	PR middle-end/94703
> 	* tree-core.h (tree_decl_common::gimple_reg_flag): Rename ...
> 	(tree_decl_common::not_gimple_reg_flag): ... to this.
> 	* tree.h (DECL_GIMPLE_REG_P): Rename ...
> 	(DECL_NOT_GIMPLE_REG_P): ... to this.
> 	* gimple-expr.c (copy_var_decl): Copy DECL_NOT_GIMPLE_REG_P.
> 	(create_tmp_reg): Simplify.
> 	(create_tmp_reg_fn): Likewise.
> 	(is_gimple_reg): Check DECL_NOT_GIMPLE_REG_P for all regs.
> 	* gimplify.c (create_tmp_from_val): Simplify.
> 	(gimplify_bind_expr): Likewise.
> 	(gimplify_compound_literal_expr): Likewise.
> 	(gimplify_function_tree): Likewise.
> 	(prepare_gimple_addressable): Set DECL_NOT_GIMPLE_REG_P.
> 	* asan.c (create_odr_indicator): Do not clear DECL_GIMPLE_REG_P.
> 	(asan_add_global): Copy it.
> 	* cgraphunit.c (cgraph_node::expand_thunk): Force args
> 	to be GIMPLE regs.
> 	* function.c (gimplify_parameters): Copy
> 	DECL_NOT_GIMPLE_REG_P.
> 	* ipa-param-manipulation.c
> 	(ipa_param_body_adjustments::common_initialization): Simplify.
> 	(ipa_param_body_adjustments::reset_debug_stmts): Copy
> 	DECL_NOT_GIMPLE_REG_P.
> 	* omp-low.c (lower_omp_for_scan): Do not set DECL_GIMPLE_REG_P.
> 	* sanopt.c (sanitize_rewrite_addressable_params): Likewise.
> 	* tree-cfg.c (make_blocks_1): Simplify.
> 	(verify_address): Do not verify DECL_GIMPLE_REG_P setting.
> 	* tree-eh.c (lower_eh_constructs_2): Simplify.
> 	* tree-inline.c (declare_return_variable): Adjust and
> 	generalize.
> 	(copy_decl_to_var): Copy DECL_NOT_GIMPLE_REG_P.
> 	(copy_result_decl_to_var): Likewise.
> 	* tree-into-ssa.c (pass_build_ssa::execute): Adjust comment.
> 	* tree-nested.c (create_tmp_var_for): Simplify.
> 	* tree-parloops.c (separate_decls_in_region_name): Copy
> 	DECL_NOT_GIMPLE_REG_P.
> 	* tree-sra.c (create_access_replacement): Adjust and
> 	generalize partial def support.
> 	* tree-ssa-forwprop.c (pass_forwprop::execute): Set
> 	DECL_NOT_GIMPLE_REG_P on decls we introduce partial defs on.
> 	* tree-ssa.c (maybe_optimize_var): Handle clearing of
> 	TREE_ADDRESSABLE and setting/clearing DECL_NOT_GIMPLE_REG_P
> 	independently.
> 	* lto-streamer-out.c (hash_tree): Hash DECL_NOT_GIMPLE_REG_P.
> 	* tree-streamer-out.c (pack_ts_decl_common_value_fields): Stream
> 	DECL_NOT_GIMPLE_REG_P.
> 	* tree-streamer-in.c (unpack_ts_decl_common_value_fields): Likewise.
> 	* cfgexpand.c (avoid_type_punning_on_regs): New.
> 	(discover_nonconstant_array_refs): Call
> 	avoid_type_punning_on_regs to avoid unsupported mode punning.
> 
> 	lto/
> 	* lto-common.c (compare_tree_sccs_1): Compare
> 	DECL_NOT_GIMPLE_REG_P.
> 
> 	c/
> 	* gimple-parser.c (c_parser_parse_ssa_name): Do not set
> 	DECL_GIMPLE_REG_P.
> 
> 	cp/
> 	* optimize.c (update_cloned_parm): Copy DECL_NOT_GIMPLE_REG_P.
> 
> 	* gcc.dg/tree-ssa/pr94703.c: New testcase.
> ---
>  gcc/asan.c                              |  3 +-
>  gcc/c/gimple-parser.c                   |  3 --
>  gcc/cfgexpand.c                         | 29 +++++++++++++++
>  gcc/cgraphunit.c                        |  5 +--
>  gcc/cp/optimize.c                       |  2 +-
>  gcc/function.c                          |  5 +--
>  gcc/gimple-expr.c                       | 24 +++---------
>  gcc/gimplify.c                          | 46 +----------------------
>  gcc/ipa-param-manipulation.c            |  6 +--
>  gcc/lto-streamer-out.c                  |  2 +-
>  gcc/lto/lto-common.c                    |  2 +-
>  gcc/omp-low.c                           |  1 -
>  gcc/sanopt.c                            |  1 -
>  gcc/testsuite/gcc.dg/tree-ssa/pr94703.c | 11 ++++++
>  gcc/tree-cfg.c                          |  9 -----
>  gcc/tree-core.h                         |  2 +-
>  gcc/tree-eh.c                           |  3 --
>  gcc/tree-inline.c                       | 28 +++++++-------
>  gcc/tree-into-ssa.c                     |  3 +-
>  gcc/tree-nested.c                       |  3 --
>  gcc/tree-parloops.c                     |  2 +-
>  gcc/tree-sra.c                          | 12 ++----
>  gcc/tree-ssa-forwprop.c                 |  6 ++-
>  gcc/tree-ssa.c                          | 66 +++++++++++++++++----------------
>  gcc/tree-streamer-in.c                  |  2 +-
>  gcc/tree-streamer-out.c                 |  2 +-
>  gcc/tree.h                              |  4 +-
>  27 files changed, 118 insertions(+), 164 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94703.c
> 
> diff --git a/gcc/asan.c b/gcc/asan.c
> index ae14f7e543c..c9872f1b007 100644
> --- a/gcc/asan.c
> +++ b/gcc/asan.c
> @@ -2696,7 +2696,6 @@ create_odr_indicator (tree decl, tree type)
>    TREE_ADDRESSABLE (var) = 1;
>    TREE_READONLY (var) = 0;
>    TREE_THIS_VOLATILE (var) = 1;
> -  DECL_GIMPLE_REG_P (var) = 0;
>    DECL_ARTIFICIAL (var) = 1;
>    DECL_IGNORED_P (var) = 1;
>    TREE_STATIC (var) = 1;
> @@ -2766,7 +2765,7 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
>        TREE_ADDRESSABLE (refdecl) = TREE_ADDRESSABLE (decl);
>        TREE_READONLY (refdecl) = TREE_READONLY (decl);
>        TREE_THIS_VOLATILE (refdecl) = TREE_THIS_VOLATILE (decl);
> -      DECL_GIMPLE_REG_P (refdecl) = DECL_GIMPLE_REG_P (decl);
> +      DECL_NOT_GIMPLE_REG_P (refdecl) = DECL_NOT_GIMPLE_REG_P (decl);
>        DECL_ARTIFICIAL (refdecl) = DECL_ARTIFICIAL (decl);
>        DECL_IGNORED_P (refdecl) = DECL_IGNORED_P (decl);
>        TREE_STATIC (refdecl) = 1;
> diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
> index 4e8ff5b1c4f..577d8b58c7d 100644
> --- a/gcc/c/gimple-parser.c
> +++ b/gcc/c/gimple-parser.c
> @@ -1272,9 +1272,6 @@ c_parser_parse_ssa_name (gimple_parser &parser,
>  	      error ("invalid base %qE for SSA name", parent);
>  	      return error_mark_node;
>  	    }
> -	  if (VECTOR_TYPE_P (TREE_TYPE (parent))
> -	      || TREE_CODE (TREE_TYPE (parent)) == COMPLEX_TYPE)
> -	    DECL_GIMPLE_REG_P (parent) = 1;
>  	  name = make_ssa_name_fn (cfun, parent,
>  				   gimple_build_nop (), version);
>  	}
> diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> index a7ec77d5c85..2d39c5e43c5 100644
> --- a/gcc/cfgexpand.c
> +++ b/gcc/cfgexpand.c
> @@ -6126,6 +6126,29 @@ discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
>    return NULL_TREE;
>  }
>  
> +/* If there's a chance to get a pseudo for t then if it would be of float mode
> +   and the actual access is via an integer mode (lowered memcpy or similar
> +   access) then avoid the register expansion if the mode likely is not storage
> +   suitable for raw bits processing (like XFmode on i?86).  */
> +
> +static void
> +avoid_type_punning_on_regs (tree t)
> +{
> +  machine_mode access_mode = TYPE_MODE (TREE_TYPE (t));
> +  if (access_mode != BLKmode
> +      && !SCALAR_INT_MODE_P (access_mode))
> +    return;
> +  tree base = get_base_address (t);
> +  if (DECL_P (base)
> +      && !TREE_ADDRESSABLE (base)
> +      && FLOAT_MODE_P (DECL_MODE (base))
> +      && maybe_lt (GET_MODE_PRECISION (DECL_MODE (base)),
> +		   GET_MODE_BITSIZE (GET_MODE_INNER (DECL_MODE (base))))
> +      /* Double check in the expensive way we really would get a pseudo.  */
> +      && use_register_for_decl (base))
> +    TREE_ADDRESSABLE (base) = 1;
> +}
> +
>  /* RTL expansion is not able to compile array references with variable
>     offsets for arrays stored in single register.  Discover such
>     expressions and mark variables as addressable to avoid this
> @@ -6159,6 +6182,12 @@ discover_nonconstant_array_refs (void)
>  		default:
>  		  break;
>  		}
> +	    if (gimple_vdef (stmt))
> +	      {
> +		tree t = gimple_get_lhs (stmt);
> +		if (t && REFERENCE_CLASS_P (t))
> +		  avoid_type_punning_on_regs (t);
> +	      }
>  	  }
>        }
>  }
> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> index a1ace95879a..0563932a709 100644
> --- a/gcc/cgraphunit.c
> +++ b/gcc/cgraphunit.c
> @@ -2058,10 +2058,7 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
>  	for (; i < nargs; i++, arg = DECL_CHAIN (arg))
>  	  {
>  	    tree tmp = arg;
> -	    if (VECTOR_TYPE_P (TREE_TYPE (arg))
> -		|| TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
> -	      DECL_GIMPLE_REG_P (arg) = 1;
> -
> +	    DECL_NOT_GIMPLE_REG_P (arg) = 0;
>  	    if (!is_gimple_val (arg))
>  	      {
>  		tmp = create_tmp_reg (TYPE_MAIN_VARIANT
> diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
> index d4f12dbb84d..abdcd7fa19f 100644
> --- a/gcc/cp/optimize.c
> +++ b/gcc/cp/optimize.c
> @@ -58,7 +58,7 @@ update_cloned_parm (tree parm, tree cloned_parm, bool first)
>    DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
>    TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
>  
> -  DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm);
> +  DECL_NOT_GIMPLE_REG_P (cloned_parm) = DECL_NOT_GIMPLE_REG_P (parm);
>  }
>  
>  /* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
> diff --git a/gcc/function.c b/gcc/function.c
> index d616f5f64f4..9eee9b59bfd 100644
> --- a/gcc/function.c
> +++ b/gcc/function.c
> @@ -3913,9 +3913,8 @@ gimplify_parameters (gimple_seq *cleanup)
>  		     as we'll query that flag during gimplification.  */
>  		  if (TREE_ADDRESSABLE (parm))
>  		    TREE_ADDRESSABLE (local) = 1;
> -		  else if (TREE_CODE (type) == COMPLEX_TYPE
> -			   || TREE_CODE (type) == VECTOR_TYPE)
> -		    DECL_GIMPLE_REG_P (local) = 1;
> +		  if (DECL_NOT_GIMPLE_REG_P (parm))
> +		    DECL_NOT_GIMPLE_REG_P (local) = 1;
>  
>  		  if (!is_gimple_reg (local)
>  		      && flag_stack_reuse != SR_NONE)
> diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
> index 44a0b8790f5..45871ac2c27 100644
> --- a/gcc/gimple-expr.c
> +++ b/gcc/gimple-expr.c
> @@ -373,7 +373,7 @@ copy_var_decl (tree var, tree name, tree type)
>  
>    TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
>    TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
> -  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
> +  DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (var);
>    DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
>    DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
>    DECL_CONTEXT (copy) = DECL_CONTEXT (var);
> @@ -493,14 +493,7 @@ create_tmp_var (tree type, const char *prefix)
>  tree
>  create_tmp_reg (tree type, const char *prefix)
>  {
> -  tree tmp;
> -
> -  tmp = create_tmp_var (type, prefix);
> -  if (TREE_CODE (type) == COMPLEX_TYPE
> -      || TREE_CODE (type) == VECTOR_TYPE)
> -    DECL_GIMPLE_REG_P (tmp) = 1;
> -
> -  return tmp;
> +  return create_tmp_var (type, prefix);
>  }
>  
>  /* Create a new temporary variable declaration of type TYPE by calling
> @@ -514,9 +507,6 @@ create_tmp_reg_fn (struct function *fn, tree type, const char *prefix)
>  
>    tmp = create_tmp_var_raw (type, prefix);
>    gimple_add_tmp_var_fn (fn, tmp);
> -  if (TREE_CODE (type) == COMPLEX_TYPE
> -      || TREE_CODE (type) == VECTOR_TYPE)
> -    DECL_GIMPLE_REG_P (tmp) = 1;
>  
>    return tmp;
>  }
> @@ -792,13 +782,9 @@ is_gimple_reg (tree t)
>    if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
>      return false;
>  
> -  /* Complex and vector values must have been put into SSA-like form.
> -     That is, no assignments to the individual components.  */
> -  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
> -      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
> -    return DECL_GIMPLE_REG_P (t);
> -
> -  return true;
> +  /* Variables can be marked as having partial definitions, avoid
> +     putting them into SSA form.  */
> +  return !DECL_NOT_GIMPLE_REG_P (t);
>  }
>  
>  
> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> index 2f2c51b2d89..ef7679d4c2b 100644
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -559,9 +559,6 @@ create_tmp_from_val (tree val)
>    /* Drop all qualifiers and address-space information from the value type.  */
>    tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
>    tree var = create_tmp_var (type, get_name (val));
> -  if (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
> -      || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE)
> -    DECL_GIMPLE_REG_P (var) = 1;
>    return var;
>  }
>  
> @@ -1400,16 +1397,6 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
>  	  if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
>  	    cfun->has_local_explicit_reg_vars = true;
>  	}
> -
> -      /* Preliminarily mark non-addressed complex variables as eligible
> -	 for promotion to gimple registers.  We'll transform their uses
> -	 as we find them.  */
> -      if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
> -	   || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
> -	  && !TREE_THIS_VOLATILE (t)
> -	  && (VAR_P (t) && !DECL_HARD_REGISTER (t))
> -	  && !needs_to_live_in_memory (t))
> -	DECL_GIMPLE_REG_P (t) = 1;
>      }
>  
>    bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
> @@ -4308,7 +4295,7 @@ prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
>      {
>        /* Do not allow an SSA name as the temporary.  */
>        tree var = get_initialized_tmp_var (*expr_p, seq_p, NULL, false);
> -      DECL_GIMPLE_REG_P (var) = 0;
> +      DECL_NOT_GIMPLE_REG_P (var) = 1;
>        *expr_p = var;
>      }
>  }
> @@ -4774,15 +4761,6 @@ gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
>        return GS_OK;
>      }
>  
> -  /* Preliminarily mark non-addressed complex variables as eligible
> -     for promotion to gimple registers.  We'll transform their uses
> -     as we find them.  */
> -  if ((TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE
> -       || TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE)
> -      && !TREE_THIS_VOLATILE (decl)
> -      && !needs_to_live_in_memory (decl))
> -    DECL_GIMPLE_REG_P (decl) = 1;
> -
>    /* If the decl is not addressable, then it is being used in some
>       expression or on the right hand side of a statement, and it can
>       be put into a readonly data section.  */
> @@ -5617,8 +5595,7 @@ is_gimple_stmt (tree t)
>  
>  
>  /* Promote partial stores to COMPLEX variables to total stores.  *EXPR_P is
> -   a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a variable with
> -   DECL_GIMPLE_REG_P set.
> +   a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register.
>  
>     IMPORTANT NOTE: This promotion is performed by introducing a load of the
>     other, unmodified part of the complex object just before the total store.
> @@ -14992,7 +14969,6 @@ flag_instrument_functions_exclude_p (tree fndecl)
>  void
>  gimplify_function_tree (tree fndecl)
>  {
> -  tree parm, ret;
>    gimple_seq seq;
>    gbind *bind;
>  
> @@ -15007,24 +14983,6 @@ gimplify_function_tree (tree fndecl)
>       if necessary.  */
>    cfun->curr_properties |= PROP_gimple_lva;
>  
> -  for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = DECL_CHAIN (parm))
> -    {
> -      /* Preliminarily mark non-addressed complex variables as eligible
> -         for promotion to gimple registers.  We'll transform their uses
> -         as we find them.  */
> -      if ((TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE
> -	   || TREE_CODE (TREE_TYPE (parm)) == VECTOR_TYPE)
> -          && !TREE_THIS_VOLATILE (parm)
> -          && !needs_to_live_in_memory (parm))
> -        DECL_GIMPLE_REG_P (parm) = 1;
> -    }
> -
> -  ret = DECL_RESULT (fndecl);
> -  if ((TREE_CODE (TREE_TYPE (ret)) == COMPLEX_TYPE
> -       || TREE_CODE (TREE_TYPE (ret)) == VECTOR_TYPE)
> -      && !needs_to_live_in_memory (ret))
> -    DECL_GIMPLE_REG_P (ret) = 1;
> -
>    if (asan_sanitize_use_after_scope () && sanitize_flags_p (SANITIZE_ADDRESS))
>      asan_poisoned_variables = new hash_set<tree> ();
>    bind = gimplify_body (fndecl, true);
> diff --git a/gcc/ipa-param-manipulation.c b/gcc/ipa-param-manipulation.c
> index 839bd2ef870..978916057f0 100644
> --- a/gcc/ipa-param-manipulation.c
> +++ b/gcc/ipa-param-manipulation.c
> @@ -1028,10 +1028,6 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl,
>  	  DECL_CONTEXT (new_parm) = m_fndecl;
>  	  TREE_USED (new_parm) = 1;
>  	  DECL_IGNORED_P (new_parm) = 1;
> -	  /* We assume all newly created arguments are not addressable.  */
> -	  if (TREE_CODE (new_type) == COMPLEX_TYPE
> -	      || TREE_CODE (new_type) == VECTOR_TYPE)
> -	    DECL_GIMPLE_REG_P (new_parm) = 1;
>  	  layout_decl (new_parm, 0);
>  	  m_new_decls.quick_push (new_parm);
>  
> @@ -1888,7 +1884,7 @@ ipa_param_body_adjustments::reset_debug_stmts ()
>  	  TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
>  	  TREE_READONLY (copy) = TREE_READONLY (decl);
>  	  TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
> -	  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
> +	  DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
>  	  DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl);
>  	  DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl);
>  	  DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
> diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
> index 52ef94718db..c5edb6b00fd 100644
> --- a/gcc/lto-streamer-out.c
> +++ b/gcc/lto-streamer-out.c
> @@ -1067,7 +1067,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
>        hstate.add_flag (DECL_USER_ALIGN (t));
>        hstate.add_flag (DECL_PRESERVE_P (t));
>        hstate.add_flag (DECL_EXTERNAL (t));
> -      hstate.add_flag (DECL_GIMPLE_REG_P (t));
> +      hstate.add_flag (DECL_NOT_GIMPLE_REG_P (t));
>        hstate.commit_flag ();
>        hstate.add_int (DECL_ALIGN (t));
>        if (code == LABEL_DECL)
> diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
> index cee5f0e9935..afd2375c516 100644
> --- a/gcc/lto/lto-common.c
> +++ b/gcc/lto/lto-common.c
> @@ -1167,7 +1167,7 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
>        compare_values (DECL_USER_ALIGN);
>        compare_values (DECL_PRESERVE_P);
>        compare_values (DECL_EXTERNAL);
> -      compare_values (DECL_GIMPLE_REG_P);
> +      compare_values (DECL_NOT_GIMPLE_REG_P);
>        compare_values (DECL_ALIGN);
>        if (code == LABEL_DECL)
>  	{
> diff --git a/gcc/omp-low.c b/gcc/omp-low.c
> index 88f23e60d34..c8c9db43afb 100644
> --- a/gcc/omp-low.c
> +++ b/gcc/omp-low.c
> @@ -10322,7 +10322,6 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt,
>    gimple_seq_add_stmt (body_p, g);
>  
>    tree cplx = create_tmp_var (build_complex_type (unsigned_type_node, false));
> -  DECL_GIMPLE_REG_P (cplx) = 1;
>    g = gimple_build_call_internal (IFN_MUL_OVERFLOW, 2, thread_nump1, twok);
>    gimple_call_set_lhs (g, cplx);
>    gimple_seq_add_stmt (body_p, g);
> diff --git a/gcc/sanopt.c b/gcc/sanopt.c
> index 0788eef597e..86180e32c7e 100644
> --- a/gcc/sanopt.c
> +++ b/gcc/sanopt.c
> @@ -1189,7 +1189,6 @@ sanitize_rewrite_addressable_params (function *fun)
>  	    {
>  	      /* We need to create a SSA name that will be used for the
>  		 assignment.  */
> -	      DECL_GIMPLE_REG_P (arg) = 1;
>  	      tree tmp = get_or_create_ssa_default_def (cfun, arg);
>  	      g = gimple_build_assign (var, tmp);
>  	      gimple_set_location (g, DECL_SOURCE_LOCATION (arg));
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94703.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94703.c
> new file mode 100644
> index 00000000000..7209fa0a4d4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94703.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O -fdump-tree-ssa" } */
> +
> +unsigned int set_lowpart (unsigned int const *X)
> +{
> +  unsigned int r = 0;
> +  __builtin_memcpy(&r,X,sizeof (unsigned int) / 2);
> +  return r;
> +}
> +
> +/* { dg-final { scan-tree-dump "No longer having address taken: r" "ssa" } } */
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index e99fb9ff5d1..8b6548f3001 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -577,9 +577,6 @@ make_blocks_1 (gimple_seq seq, basic_block bb)
>  	      gimple_set_location (s, gimple_location (stmt));
>  	      gimple_set_block (s, gimple_block (stmt));
>  	      gimple_set_lhs (stmt, tmp);
> -	      if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
> -		  || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
> -		DECL_GIMPLE_REG_P (tmp) = 1;
>  	      gsi_insert_after (&i, s, GSI_SAME_STMT);
>  	    }
>  	  start_new_block = true;
> @@ -2983,12 +2980,6 @@ verify_address (tree t, bool verify_addressable)
>  	|| TREE_CODE (base) == RESULT_DECL))
>      return false;
>  
> -  if (DECL_GIMPLE_REG_P (base))
> -    {
> -      error ("%<DECL_GIMPLE_REG_P%> set on a variable with address taken");
> -      return true;
> -    }
> -
>    if (verify_addressable && !TREE_ADDRESSABLE (base))
>      {
>        error ("address taken but %<TREE_ADDRESSABLE%> bit not set");
> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> index d84fe959acc..9439f1ffc88 100644
> --- a/gcc/tree-core.h
> +++ b/gcc/tree-core.h
> @@ -1723,7 +1723,7 @@ struct GTY(()) tree_decl_common {
>    unsigned decl_flag_3 : 1;
>    /* Logically, these two would go in a theoretical base shared by var and
>       parm decl. */
> -  unsigned gimple_reg_flag : 1;
> +  unsigned not_gimple_reg_flag : 1;
>    /* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_BY_REFERENCE.  */
>    unsigned decl_by_reference_flag : 1;
>    /* In a VAR_DECL and PARM_DECL, this is DECL_READ_P.  */
> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> index 2a409dcaffe..10ef2e3157c 100644
> --- a/gcc/tree-eh.c
> +++ b/gcc/tree-eh.c
> @@ -2072,9 +2072,6 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
>  	  gimple_set_location (s, gimple_location (stmt));
>  	  gimple_set_block (s, gimple_block (stmt));
>  	  gimple_set_lhs (stmt, tmp);
> -	  if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
> -	      || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
> -	    DECL_GIMPLE_REG_P (tmp) = 1;
>  	  gsi_insert_after (gsi, s, GSI_SAME_STMT);
>  	}
>        /* Look for things that can throw exceptions, and record them.  */
> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> index 69ca8e99109..80f35ef9350 100644
> --- a/gcc/tree-inline.c
> +++ b/gcc/tree-inline.c
> @@ -3670,11 +3670,9 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
>  	  if (TREE_ADDRESSABLE (result))
>  	    mark_addressable (var);
>  	}
> -      if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
> -           || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE)
> -	  && !DECL_GIMPLE_REG_P (result)
> +      if (DECL_NOT_GIMPLE_REG_P (result)
>  	  && DECL_P (var))
> -	DECL_GIMPLE_REG_P (var) = 0;
> +	DECL_NOT_GIMPLE_REG_P (var) = 1;
>  
>        if (!useless_type_conversion_p (callee_type, caller_type))
>  	var = build1 (VIEW_CONVERT_EXPR, callee_type, var);
> @@ -3717,10 +3715,8 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
>  	    use_it = false;
>  	  else if (is_global_var (base_m))
>  	    use_it = false;
> -	  else if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
> -		    || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE)
> -		   && !DECL_GIMPLE_REG_P (result)
> -		   && DECL_GIMPLE_REG_P (base_m))
> +	  else if (DECL_NOT_GIMPLE_REG_P (result)
> +		   && !DECL_NOT_GIMPLE_REG_P (base_m))
>  	    use_it = false;
>  	  else if (!TREE_ADDRESSABLE (base_m))
>  	    use_it = true;
> @@ -3760,11 +3756,8 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
>  	     to using a MEM_REF to not leak invalid GIMPLE to the following
>  	     passes.  */
>  	  /* Prevent var from being written into SSA form.  */
> -	  if (TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
> -	      || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE)
> -	    DECL_GIMPLE_REG_P (var) = false;
> -	  else if (is_gimple_reg_type (TREE_TYPE (var)))
> -	    TREE_ADDRESSABLE (var) = true;
> +	  if (is_gimple_reg_type (TREE_TYPE (var)))
> +	    DECL_NOT_GIMPLE_REG_P (var) = true;
>  	  use = fold_build2 (MEM_REF, caller_type,
>  			     build_fold_addr_expr (var),
>  			     build_int_cst (ptr_type_node, 0));
> @@ -5930,7 +5923,7 @@ copy_decl_to_var (tree decl, copy_body_data *id)
>    TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
>    TREE_READONLY (copy) = TREE_READONLY (decl);
>    TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
> -  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
> +  DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
>    DECL_BY_REFERENCE (copy) = DECL_BY_REFERENCE (decl);
>  
>    return copy_decl_for_dup_finish (id, decl, copy);
> @@ -5960,7 +5953,12 @@ copy_result_decl_to_var (tree decl, copy_body_data *id)
>    if (!DECL_BY_REFERENCE (decl))
>      {
>        TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
> -      DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
> +      DECL_NOT_GIMPLE_REG_P (copy)
> +	= (DECL_NOT_GIMPLE_REG_P (decl)
> +	   /* RESULT_DECLs are treated special by needs_to_live_in_memory,
> +	      mirror that to the created VAR_DECL.  */
> +	   || (TREE_CODE (decl) == RESULT_DECL
> +	       && aggregate_value_p (decl, id->src_fn)));
>      }
>  
>    return copy_decl_for_dup_finish (id, decl, copy);
> diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
> index 6528acac31a..c24931effac 100644
> --- a/gcc/tree-into-ssa.c
> +++ b/gcc/tree-into-ssa.c
> @@ -2430,8 +2430,7 @@ pass_build_ssa::execute (function *fun)
>    basic_block bb;
>  
>    /* Increase the set of variables we can rewrite into SSA form
> -     by clearing TREE_ADDRESSABLE and setting DECL_GIMPLE_REG_P
> -     and transform the IL to support this.  */
> +     by clearing TREE_ADDRESSABLE and transform the IL to support this.  */
>    if (optimize)
>      execute_update_addresses_taken ();
>  
> diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
> index 6f696da5332..de168df70a1 100644
> --- a/gcc/tree-nested.c
> +++ b/gcc/tree-nested.c
> @@ -160,9 +160,6 @@ create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
>    DECL_CONTEXT (tmp_var) = info->context;
>    DECL_CHAIN (tmp_var) = info->new_local_var_chain;
>    DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
> -  if (TREE_CODE (type) == COMPLEX_TYPE
> -      || TREE_CODE (type) == VECTOR_TYPE)
> -    DECL_GIMPLE_REG_P (tmp_var) = 1;
>  
>    info->new_local_var_chain = tmp_var;
>  
> diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
> index d9250d36c72..8cd50234a1c 100644
> --- a/gcc/tree-parloops.c
> +++ b/gcc/tree-parloops.c
> @@ -1574,7 +1574,7 @@ separate_decls_in_region_name (tree name, name_to_copy_table_type *name_copies,
>    if (!dslot->to)
>      {
>        var_copy = create_tmp_var (TREE_TYPE (var), get_name (var));
> -      DECL_GIMPLE_REG_P (var_copy) = DECL_GIMPLE_REG_P (var);
> +      DECL_NOT_GIMPLE_REG_P (var_copy) = DECL_NOT_GIMPLE_REG_P (var);
>        dslot->uid = uid;
>        dslot->to = var_copy;
>  
> diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
> index 227bde06257..4793b48f32c 100644
> --- a/gcc/tree-sra.c
> +++ b/gcc/tree-sra.c
> @@ -2168,15 +2168,9 @@ create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
>         variant.  This avoids issues with weirdo ABIs like AAPCS.  */
>      repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT (type),
>  						 TYPE_QUALS (type)), "SR");
> -  if (TREE_CODE (type) == COMPLEX_TYPE
> -      || TREE_CODE (type) == VECTOR_TYPE)
> -    {
> -      if (!access->grp_partial_lhs)
> -	DECL_GIMPLE_REG_P (repl) = 1;
> -    }
> -  else if (access->grp_partial_lhs
> -	   && is_gimple_reg_type (type))
> -    TREE_ADDRESSABLE (repl) = 1;
> +  if (access->grp_partial_lhs
> +      && is_gimple_reg_type (type))
> +    DECL_NOT_GIMPLE_REG_P (repl) = 1;
>  
>    DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
>    DECL_ARTIFICIAL (repl) = 1;
> diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
> index 1a50045b367..b68da91723b 100644
> --- a/gcc/tree-ssa-forwprop.c
> +++ b/gcc/tree-ssa-forwprop.c
> @@ -2945,6 +2945,8 @@ pass_forwprop::execute (function *fun)
>  		      != TARGET_MEM_REF))
>  		{
>  		  tree use_lhs = gimple_assign_lhs (use_stmt);
> +		  if (auto_var_p (use_lhs))
> +		    DECL_NOT_GIMPLE_REG_P (use_lhs) = 1;
>  		  tree new_lhs = build1 (REALPART_EXPR,
>  					 TREE_TYPE (TREE_TYPE (use_lhs)),
>  					 unshare_expr (use_lhs));
> @@ -2996,6 +2998,9 @@ pass_forwprop::execute (function *fun)
>  		    = tree_to_uhwi (TYPE_SIZE (elt_t));
>  		  unsigned HOST_WIDE_INT n
>  		    = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs)));
> +		  tree use_lhs = gimple_assign_lhs (use_stmt);
> +		  if (auto_var_p (use_lhs))
> +		    DECL_NOT_GIMPLE_REG_P (use_lhs) = 1;
>  		  for (unsigned HOST_WIDE_INT bi = 0; bi < n; bi += elt_w)
>  		    {
>  		      unsigned HOST_WIDE_INT ci = bi / elt_w;
> @@ -3004,7 +3009,6 @@ pass_forwprop::execute (function *fun)
>  			new_rhs = CONSTRUCTOR_ELT (rhs, ci)->value;
>  		      else
>  			new_rhs = build_zero_cst (elt_t);
> -		      tree use_lhs = gimple_assign_lhs (use_stmt);
>  		      tree new_lhs = build3 (BIT_FIELD_REF,
>  					     elt_t,
>  					     unshare_expr (use_lhs),
> diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
> index 4f4ab2b8992..c47b963bbb2 100644
> --- a/gcc/tree-ssa.c
> +++ b/gcc/tree-ssa.c
> @@ -1583,8 +1583,8 @@ non_rewritable_lvalue_p (tree lhs)
>    return true;
>  }
>  
> -/* When possible, clear TREE_ADDRESSABLE bit or set DECL_GIMPLE_REG_P bit and
> -   mark the variable VAR for conversion into SSA.  Return true when updating
> +/* When possible, clear TREE_ADDRESSABLE bit, set or clear DECL_NOT_GIMPLE_REG_P
> +   and mark the variable VAR for conversion into SSA.  Return true when updating
>     stmts is required.  */
>  
>  static void
> @@ -1597,24 +1597,11 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs,
>        || bitmap_bit_p (addresses_taken, DECL_UID (var)))
>      return;
>  
> -  if (TREE_ADDRESSABLE (var)
> -      /* Do not change TREE_ADDRESSABLE if we need to preserve var as
> -	 a non-register.  Otherwise we are confused and forget to
> -	 add virtual operands for it.  */
> -      && (!is_gimple_reg_type (TREE_TYPE (var))
> -	  || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
> -	  || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
> -	  || !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
> +  bool maybe_reg = false;
> +  if (TREE_ADDRESSABLE (var))
>      {
>        TREE_ADDRESSABLE (var) = 0;
> -      /* If we cleared TREE_ADDRESSABLE make sure DECL_GIMPLE_REG_P
> -         is unset if we cannot rewrite the var into SSA.  */
> -      if ((TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
> -	   || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE)
> -	  && bitmap_bit_p (not_reg_needs, DECL_UID (var)))
> -	DECL_GIMPLE_REG_P (var) = 0;
> -      if (is_gimple_reg (var))
> -	bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
> +      maybe_reg = true;
>        if (dump_file)
>  	{
>  	  fprintf (dump_file, "No longer having address taken: ");
> @@ -1623,20 +1610,36 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs,
>  	}
>      }
>  
> -  if (!DECL_GIMPLE_REG_P (var)
> -      && !bitmap_bit_p (not_reg_needs, DECL_UID (var))
> -      && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
> -	  || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE)
> -      && !TREE_THIS_VOLATILE (var)
> -      && (!VAR_P (var) || !DECL_HARD_REGISTER (var)))
> +  /* For register type decls if we do not have any partial defs
> +     we cannot express in SSA form mark them as DECL_NOT_GIMPLE_REG_P
> +     as to avoid SSA rewrite.  For the others go ahead and mark
> +     them for renaming.  */
> +  if (is_gimple_reg_type (TREE_TYPE (var)))
>      {
> -      DECL_GIMPLE_REG_P (var) = 1;
> -      bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
> -      if (dump_file)
> +      if (bitmap_bit_p (not_reg_needs, DECL_UID (var)))
>  	{
> -	  fprintf (dump_file, "Now a gimple register: ");
> -	  print_generic_expr (dump_file, var);
> -	  fprintf (dump_file, "\n");
> +	  DECL_NOT_GIMPLE_REG_P (var) = 1;
> +	  if (dump_file)
> +	    {
> +	      fprintf (dump_file, "Has partial defs: ");
> +	      print_generic_expr (dump_file, var);
> +	      fprintf (dump_file, "\n");
> +	    }
> +	}
> +      else if (DECL_NOT_GIMPLE_REG_P (var))
> +	{
> +	  maybe_reg = true;
> +	  DECL_NOT_GIMPLE_REG_P (var) = 0;
> +	}
> +      if (maybe_reg && is_gimple_reg (var))
> +	{
> +	  if (dump_file)
> +	    {
> +	      fprintf (dump_file, "Now a gimple register: ");
> +	      print_generic_expr (dump_file, var);
> +	      fprintf (dump_file, "\n");
> +	    }
> +	  bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
>  	}
>      }
>  }
> @@ -1669,7 +1672,8 @@ is_asan_mark_p (gimple *stmt)
>    return false;
>  }
>  
> -/* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables.  */
> +/* Compute TREE_ADDRESSABLE and whether we have unhandled partial defs
> +   for local variables.  */
>  
>  void
>  execute_update_addresses_taken (void)
> diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
> index 0bfc272d076..79b97ffa9a3 100644
> --- a/gcc/tree-streamer-in.c
> +++ b/gcc/tree-streamer-in.c
> @@ -236,7 +236,7 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
>    DECL_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
>    DECL_PRESERVE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
>    DECL_EXTERNAL (expr) = (unsigned) bp_unpack_value (bp, 1);
> -  DECL_GIMPLE_REG_P (expr) = (unsigned) bp_unpack_value (bp, 1);
> +  DECL_NOT_GIMPLE_REG_P (expr) = (unsigned) bp_unpack_value (bp, 1);
>    SET_DECL_ALIGN (expr, (unsigned) bp_unpack_var_len_unsigned (bp));
>  #ifdef ACCEL_COMPILER
>    if (DECL_ALIGN (expr) > targetm.absolute_biggest_alignment)
> diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
> index 5bbcebba87e..3ab8c889a23 100644
> --- a/gcc/tree-streamer-out.c
> +++ b/gcc/tree-streamer-out.c
> @@ -201,7 +201,7 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
>    bp_pack_value (bp, DECL_USER_ALIGN (expr), 1);
>    bp_pack_value (bp, DECL_PRESERVE_P (expr), 1);
>    bp_pack_value (bp, DECL_EXTERNAL (expr), 1);
> -  bp_pack_value (bp, DECL_GIMPLE_REG_P (expr), 1);
> +  bp_pack_value (bp, DECL_NOT_GIMPLE_REG_P (expr), 1);
>    bp_pack_var_len_unsigned (bp, DECL_ALIGN (expr));
>  
>    if (TREE_CODE (expr) == LABEL_DECL)
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 1c28785d411..66042c14290 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -2646,8 +2646,8 @@ extern machine_mode vector_type_mode (const_tree);
>     they are killing assignments.  Thus the variable may now
>     be treated as a GIMPLE register, and use real instead of
>     virtual ops in SSA form.  */
> -#define DECL_GIMPLE_REG_P(DECL) \
> -  DECL_COMMON_CHECK (DECL)->decl_common.gimple_reg_flag
> +#define DECL_NOT_GIMPLE_REG_P(DECL) \
> +  DECL_COMMON_CHECK (DECL)->decl_common.not_gimple_reg_flag
>  
>  extern tree decl_value_expr_lookup (tree);
>  extern void decl_value_expr_insert (tree, tree);
>
Alex Coplan June 4, 2020, 9:34 a.m. UTC | #5
> -----Original Message-----
> From: Gcc-patches <gcc-patches-bounces@gcc.gnu.org> On Behalf Of Richard
> Biener
> Sent: 07 May 2020 14:40
> To: Richard Sandiford <Richard.Sandiford@arm.com>
> Cc: gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH][RFC] extend DECL_GIMPLE_REG_P to all types
> 
> On Thu, 23 Apr 2020, Richard Biener wrote:
> 
> > On Wed, 22 Apr 2020, Richard Sandiford wrote:
> >
> > > Richard Biener <rguenther@suse.de> writes:
> > > > On Wed, 22 Apr 2020, Richard Biener wrote:
> > > >
> > > >>
> > > >> This extends DECL_GIMPLE_REG_P to all types so we can clear
> > > >> TREE_ADDRESSABLE even for integers with partial defs, not just
> > > >> complex and vector variables.  To make that transition easier
> > > >> the patch inverts DECL_GIMPLE_REG_P to DECL_NOT_GIMPLE_REG_P
> > > >> since that makes the default the current state for all other
> > > >> types besides complex and vectors.  That also nicely simplifies
> > > >> code throughout the compiler.
> > > >>
> > > >> TREE_ADDRESSABLE and DECL_NOT_GIMPLE_REG_P are now truly
> > > >> independent, either set prevents a decl from being rewritten
> > > >> into SSA form.
> > > >>
> > > >> For the testcase in PR94703 we're able to expand the partial
> > > >> def'ed local integer to a register then, producing a single
> > > >> movl rather than going through the stack.
> > > >>
> > > >> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
> > > >>
> > > >> If there are no objections I'm going to install this once
> > > >> stage1 opens.
> > > >
> > > > Of course there was some fallout.  On 32bit x86
> gcc.dg/torture/pr71522.c
> > > > fails execution because while the GIMPLE is unchanged at RTL
> expansion
> > > > time:
> > > >
> > > > main ()
> > > > {
> > > >   char s[12];
> > > >   long double d;
> > > >
> > > >   MEM <unsigned char[12]> [(char * {ref-all})&d] = MEM <unsigned
> char[12]>
> > > > [(char * {ref-all})"AAAAAAAAAAA"];
> > > >   MEM <unsigned char[12]> [(char * {ref-all})&s] = MEM <unsigned
> char[12]>
> > > > [(char * {ref-all})&d];
> > > >   _1 = __builtin_strcmp (&s, "AAAAAAAAAAA");
> > > >   if (_1 != 0)
> > > > ...
> > > >
> > > > we now assign 'd' an XFmode register (TREE_ADDRESSABLE is cleared
> > > > now since we can set DECL_NOT_GIMPLE_REG_P).  The case is lost
> > > > then, impossible to fix up AFAICS.  On x86 all moves to/from
> > > > XFmode are normalizing, specifically we end up with
> > > >
> > > >         fldt    .LC0
> > > >         fstpt   (%esp)
> > > >
> > > > now the most appealing solution - and totally in the opposite
> > > > direction of this patch - is to simply stop expanding non-SSA names
> > > > as pseudos.  I do not remember the history as why we do this
> > > > but it's likely remanents we preserved from either pre-SSA, times
> > > > we did not go into SSA for -O0 or times we really gone out-of-SSA.
> > > >
> > > > There is _some_ good reason to expand a non-SSA "register" into
> > > > a pseudo though - namely that RTL is not SSA and thus can accept
> > > > partial defs.  And of course that RTL cannot get rid of a stack
> > > > slot assigned to a variable.  Today we have somewhat robust
> > > > infrastructure to deal with partial defs on GIMPLE, namely
> > > > BIT_INSERT_EXPR, but it's not fully exercised.
> > >
> > > Yeah, not being able to get rid of the stack slot seems
> > > worrying here.
> > >
> > > > It's of course possible to fixup the above problematical
> > > > cases (there's precenent with discover_nonconstant_array_refs,
> > > > which could be "easily" extended to handle "weird" accesses
> > > > of non-integral-mode variables) but with the recent discussion
> > > > on making RTL expansion more straight-forward I'd bring up
> > > > the above idea ... it would get rid of quite some special
> > > > code dealing with tcc_reference trees (and MEM_REFs) ending
> > > > up operating on registers.
> > >
> > > It might be nice to do it eventually, but I think at least
> > > is_gimple_reg_type would need to be "return true" first,
> > > otherwise we'll lose too much on aggregates.
> > >
> > > There's also the problem that things passed in registers do need
> > > to be RTL registers at function boundaries, so I'm not sure all
> > > the expand code would necessarily go away.
> > >
> > > Wouldn't want to see all targets suffer for XFmode oddities :-)
> >
> > OK, so here's the patch amemded with some heuristics to catch
> > this.  The heuristic triggers exactly on the previously
> > failing testcase and nothing else on a x86_64 bootstrap and regtest.
> > Citing the code:
> >
> > /* If there's a chance to get a pseudo for t then if it would be of
> float
> > mode
> >    and the actual access is via an integer mode (lowered memcpy or
> similar
> >    access) then avoid the register expansion if the mode likely is not
> > storage
> >    suitable for raw bits processing (like XFmode on i?86).  */
> >
> > static void
> > avoid_type_punning_on_regs (tree t)
> > {
> >   machine_mode access_mode = TYPE_MODE (TREE_TYPE (t));
> >   if (access_mode != BLKmode
> >       && !SCALAR_INT_MODE_P (access_mode))
> >     return;
> >   tree base = get_base_address (t);
> >   if (DECL_P (base)
> >       && !TREE_ADDRESSABLE (base)
> >       && FLOAT_MODE_P (DECL_MODE (base))
> >       && maybe_lt (GET_MODE_PRECISION (DECL_MODE (base)),
> >                    GET_MODE_BITSIZE (GET_MODE_INNER (DECL_MODE
> (base))))
> >       /* Double check in the expensive way we really would get a
> pseudo.
> > */
> >       && use_register_for_decl (base))
> >     TREE_ADDRESSABLE (base) = 1;
> > }
> >
> > invoked on stores like
> >
> >             if (gimple_vdef (stmt))
> >               {
> >                 tree t = gimple_get_lhs (stmt);
> >                 if (t && REFERENCE_CLASS_P (t))
> >                   avoid_type_punning_on_regs (t);
> >               }
> >
> > loads are not an issue on their own.  So the basic idea is to rule
> > out float-mode pseudos which have less precision than their mode
> > but where we store to with integer-like modes.  A but hand-wavy
> > since similar issues might exist with partial integer modes as
> storage(?),
> > but we shouldn't really need this at all in an ideal world.
> >
> > You could check whether this triggers on arm with the respective
> > long double testcase.
> >
> > Bootstrapped and tested on x86_64-unknown-linux-gnu, queued for stage1.
> 
> I have now pushed this.
> 
> Richard.

Hi Richard,

This introduces a wrong code bug on AArch64:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95526

Thanks,
Alex
diff mbox series

Patch

diff --git a/gcc/asan.c b/gcc/asan.c
index ae14f7e543c..c9872f1b007 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -2696,7 +2696,6 @@  create_odr_indicator (tree decl, tree type)
   TREE_ADDRESSABLE (var) = 1;
   TREE_READONLY (var) = 0;
   TREE_THIS_VOLATILE (var) = 1;
-  DECL_GIMPLE_REG_P (var) = 0;
   DECL_ARTIFICIAL (var) = 1;
   DECL_IGNORED_P (var) = 1;
   TREE_STATIC (var) = 1;
@@ -2766,7 +2765,7 @@  asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
       TREE_ADDRESSABLE (refdecl) = TREE_ADDRESSABLE (decl);
       TREE_READONLY (refdecl) = TREE_READONLY (decl);
       TREE_THIS_VOLATILE (refdecl) = TREE_THIS_VOLATILE (decl);
-      DECL_GIMPLE_REG_P (refdecl) = DECL_GIMPLE_REG_P (decl);
+      DECL_NOT_GIMPLE_REG_P (refdecl) = DECL_NOT_GIMPLE_REG_P (decl);
       DECL_ARTIFICIAL (refdecl) = DECL_ARTIFICIAL (decl);
       DECL_IGNORED_P (refdecl) = DECL_IGNORED_P (decl);
       TREE_STATIC (refdecl) = 1;
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 4e8ff5b1c4f..577d8b58c7d 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -1272,9 +1272,6 @@  c_parser_parse_ssa_name (gimple_parser &parser,
 	      error ("invalid base %qE for SSA name", parent);
 	      return error_mark_node;
 	    }
-	  if (VECTOR_TYPE_P (TREE_TYPE (parent))
-	      || TREE_CODE (TREE_TYPE (parent)) == COMPLEX_TYPE)
-	    DECL_GIMPLE_REG_P (parent) = 1;
 	  name = make_ssa_name_fn (cfun, parent,
 				   gimple_build_nop (), version);
 	}
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index a1ace95879a..0563932a709 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2058,10 +2058,7 @@  cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
 	for (; i < nargs; i++, arg = DECL_CHAIN (arg))
 	  {
 	    tree tmp = arg;
-	    if (VECTOR_TYPE_P (TREE_TYPE (arg))
-		|| TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-	      DECL_GIMPLE_REG_P (arg) = 1;
-
+	    DECL_NOT_GIMPLE_REG_P (arg) = 0;
 	    if (!is_gimple_val (arg))
 	      {
 		tmp = create_tmp_reg (TYPE_MAIN_VARIANT
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index d4f12dbb84d..abdcd7fa19f 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -58,7 +58,7 @@  update_cloned_parm (tree parm, tree cloned_parm, bool first)
   DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
   TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
 
-  DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm);
+  DECL_NOT_GIMPLE_REG_P (cloned_parm) = DECL_NOT_GIMPLE_REG_P (parm);
 }
 
 /* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
diff --git a/gcc/function.c b/gcc/function.c
index d616f5f64f4..9eee9b59bfd 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -3913,9 +3913,8 @@  gimplify_parameters (gimple_seq *cleanup)
 		     as we'll query that flag during gimplification.  */
 		  if (TREE_ADDRESSABLE (parm))
 		    TREE_ADDRESSABLE (local) = 1;
-		  else if (TREE_CODE (type) == COMPLEX_TYPE
-			   || TREE_CODE (type) == VECTOR_TYPE)
-		    DECL_GIMPLE_REG_P (local) = 1;
+		  if (DECL_NOT_GIMPLE_REG_P (parm))
+		    DECL_NOT_GIMPLE_REG_P (local) = 1;
 
 		  if (!is_gimple_reg (local)
 		      && flag_stack_reuse != SR_NONE)
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index 44a0b8790f5..45871ac2c27 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -373,7 +373,7 @@  copy_var_decl (tree var, tree name, tree type)
 
   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
-  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
+  DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (var);
   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
   DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
   DECL_CONTEXT (copy) = DECL_CONTEXT (var);
@@ -493,14 +493,7 @@  create_tmp_var (tree type, const char *prefix)
 tree
 create_tmp_reg (tree type, const char *prefix)
 {
-  tree tmp;
-
-  tmp = create_tmp_var (type, prefix);
-  if (TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (tmp) = 1;
-
-  return tmp;
+  return create_tmp_var (type, prefix);
 }
 
 /* Create a new temporary variable declaration of type TYPE by calling
@@ -514,9 +507,6 @@  create_tmp_reg_fn (struct function *fn, tree type, const char *prefix)
 
   tmp = create_tmp_var_raw (type, prefix);
   gimple_add_tmp_var_fn (fn, tmp);
-  if (TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (tmp) = 1;
 
   return tmp;
 }
@@ -792,13 +782,9 @@  is_gimple_reg (tree t)
   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
     return false;
 
-  /* Complex and vector values must have been put into SSA-like form.
-     That is, no assignments to the individual components.  */
-  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-    return DECL_GIMPLE_REG_P (t);
-
-  return true;
+  /* Variables can be marked as having partial definitions, avoid
+     putting them into SSA form.  */
+  return !DECL_NOT_GIMPLE_REG_P (t);
 }
 
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 2f2c51b2d89..ef7679d4c2b 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -559,9 +559,6 @@  create_tmp_from_val (tree val)
   /* Drop all qualifiers and address-space information from the value type.  */
   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
   tree var = create_tmp_var (type, get_name (val));
-  if (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (var) = 1;
   return var;
 }
 
@@ -1400,16 +1397,6 @@  gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
 	  if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
 	    cfun->has_local_explicit_reg_vars = true;
 	}
-
-      /* Preliminarily mark non-addressed complex variables as eligible
-	 for promotion to gimple registers.  We'll transform their uses
-	 as we find them.  */
-      if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-	   || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-	  && !TREE_THIS_VOLATILE (t)
-	  && (VAR_P (t) && !DECL_HARD_REGISTER (t))
-	  && !needs_to_live_in_memory (t))
-	DECL_GIMPLE_REG_P (t) = 1;
     }
 
   bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
@@ -4308,7 +4295,7 @@  prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
     {
       /* Do not allow an SSA name as the temporary.  */
       tree var = get_initialized_tmp_var (*expr_p, seq_p, NULL, false);
-      DECL_GIMPLE_REG_P (var) = 0;
+      DECL_NOT_GIMPLE_REG_P (var) = 1;
       *expr_p = var;
     }
 }
@@ -4774,15 +4761,6 @@  gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
       return GS_OK;
     }
 
-  /* Preliminarily mark non-addressed complex variables as eligible
-     for promotion to gimple registers.  We'll transform their uses
-     as we find them.  */
-  if ((TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE
-       || TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE)
-      && !TREE_THIS_VOLATILE (decl)
-      && !needs_to_live_in_memory (decl))
-    DECL_GIMPLE_REG_P (decl) = 1;
-
   /* If the decl is not addressable, then it is being used in some
      expression or on the right hand side of a statement, and it can
      be put into a readonly data section.  */
@@ -5617,8 +5595,7 @@  is_gimple_stmt (tree t)
 
 
 /* Promote partial stores to COMPLEX variables to total stores.  *EXPR_P is
-   a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a variable with
-   DECL_GIMPLE_REG_P set.
+   a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register.
 
    IMPORTANT NOTE: This promotion is performed by introducing a load of the
    other, unmodified part of the complex object just before the total store.
@@ -14992,7 +14969,6 @@  flag_instrument_functions_exclude_p (tree fndecl)
 void
 gimplify_function_tree (tree fndecl)
 {
-  tree parm, ret;
   gimple_seq seq;
   gbind *bind;
 
@@ -15007,24 +14983,6 @@  gimplify_function_tree (tree fndecl)
      if necessary.  */
   cfun->curr_properties |= PROP_gimple_lva;
 
-  for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = DECL_CHAIN (parm))
-    {
-      /* Preliminarily mark non-addressed complex variables as eligible
-         for promotion to gimple registers.  We'll transform their uses
-         as we find them.  */
-      if ((TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE
-	   || TREE_CODE (TREE_TYPE (parm)) == VECTOR_TYPE)
-          && !TREE_THIS_VOLATILE (parm)
-          && !needs_to_live_in_memory (parm))
-        DECL_GIMPLE_REG_P (parm) = 1;
-    }
-
-  ret = DECL_RESULT (fndecl);
-  if ((TREE_CODE (TREE_TYPE (ret)) == COMPLEX_TYPE
-       || TREE_CODE (TREE_TYPE (ret)) == VECTOR_TYPE)
-      && !needs_to_live_in_memory (ret))
-    DECL_GIMPLE_REG_P (ret) = 1;
-
   if (asan_sanitize_use_after_scope () && sanitize_flags_p (SANITIZE_ADDRESS))
     asan_poisoned_variables = new hash_set<tree> ();
   bind = gimplify_body (fndecl, true);
diff --git a/gcc/ipa-param-manipulation.c b/gcc/ipa-param-manipulation.c
index 839bd2ef870..978916057f0 100644
--- a/gcc/ipa-param-manipulation.c
+++ b/gcc/ipa-param-manipulation.c
@@ -1028,10 +1028,6 @@  ipa_param_body_adjustments::common_initialization (tree old_fndecl,
 	  DECL_CONTEXT (new_parm) = m_fndecl;
 	  TREE_USED (new_parm) = 1;
 	  DECL_IGNORED_P (new_parm) = 1;
-	  /* We assume all newly created arguments are not addressable.  */
-	  if (TREE_CODE (new_type) == COMPLEX_TYPE
-	      || TREE_CODE (new_type) == VECTOR_TYPE)
-	    DECL_GIMPLE_REG_P (new_parm) = 1;
 	  layout_decl (new_parm, 0);
 	  m_new_decls.quick_push (new_parm);
 
@@ -1888,7 +1884,7 @@  ipa_param_body_adjustments::reset_debug_stmts ()
 	  TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
 	  TREE_READONLY (copy) = TREE_READONLY (decl);
 	  TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
-	  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
+	  DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
 	  DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl);
 	  DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl);
 	  DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 52ef94718db..c5edb6b00fd 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -1067,7 +1067,7 @@  hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
       hstate.add_flag (DECL_USER_ALIGN (t));
       hstate.add_flag (DECL_PRESERVE_P (t));
       hstate.add_flag (DECL_EXTERNAL (t));
-      hstate.add_flag (DECL_GIMPLE_REG_P (t));
+      hstate.add_flag (DECL_NOT_GIMPLE_REG_P (t));
       hstate.commit_flag ();
       hstate.add_int (DECL_ALIGN (t));
       if (code == LABEL_DECL)
diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index cee5f0e9935..afd2375c516 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -1167,7 +1167,7 @@  compare_tree_sccs_1 (tree t1, tree t2, tree **map)
       compare_values (DECL_USER_ALIGN);
       compare_values (DECL_PRESERVE_P);
       compare_values (DECL_EXTERNAL);
-      compare_values (DECL_GIMPLE_REG_P);
+      compare_values (DECL_NOT_GIMPLE_REG_P);
       compare_values (DECL_ALIGN);
       if (code == LABEL_DECL)
 	{
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 88f23e60d34..c8c9db43afb 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -10322,7 +10322,6 @@  lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt,
   gimple_seq_add_stmt (body_p, g);
 
   tree cplx = create_tmp_var (build_complex_type (unsigned_type_node, false));
-  DECL_GIMPLE_REG_P (cplx) = 1;
   g = gimple_build_call_internal (IFN_MUL_OVERFLOW, 2, thread_nump1, twok);
   gimple_call_set_lhs (g, cplx);
   gimple_seq_add_stmt (body_p, g);
diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 0788eef597e..86180e32c7e 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -1189,7 +1189,6 @@  sanitize_rewrite_addressable_params (function *fun)
 	    {
 	      /* We need to create a SSA name that will be used for the
 		 assignment.  */
-	      DECL_GIMPLE_REG_P (arg) = 1;
 	      tree tmp = get_or_create_ssa_default_def (cfun, arg);
 	      g = gimple_build_assign (var, tmp);
 	      gimple_set_location (g, DECL_SOURCE_LOCATION (arg));
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94703.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94703.c
new file mode 100644
index 00000000000..7209fa0a4d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94703.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-ssa" } */
+
+unsigned int set_lowpart (unsigned int const *X)
+{
+  unsigned int r = 0;
+  __builtin_memcpy(&r,X,sizeof (unsigned int) / 2);
+  return r;
+}
+
+/* { dg-final { scan-tree-dump "No longer having address taken: r" "ssa" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index e99fb9ff5d1..8b6548f3001 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -577,9 +577,6 @@  make_blocks_1 (gimple_seq seq, basic_block bb)
 	      gimple_set_location (s, gimple_location (stmt));
 	      gimple_set_block (s, gimple_block (stmt));
 	      gimple_set_lhs (stmt, tmp);
-	      if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
-		  || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
-		DECL_GIMPLE_REG_P (tmp) = 1;
 	      gsi_insert_after (&i, s, GSI_SAME_STMT);
 	    }
 	  start_new_block = true;
@@ -2983,12 +2980,6 @@  verify_address (tree t, bool verify_addressable)
 	|| TREE_CODE (base) == RESULT_DECL))
     return false;
 
-  if (DECL_GIMPLE_REG_P (base))
-    {
-      error ("%<DECL_GIMPLE_REG_P%> set on a variable with address taken");
-      return true;
-    }
-
   if (verify_addressable && !TREE_ADDRESSABLE (base))
     {
       error ("address taken but %<TREE_ADDRESSABLE%> bit not set");
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index d84fe959acc..9439f1ffc88 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1723,7 +1723,7 @@  struct GTY(()) tree_decl_common {
   unsigned decl_flag_3 : 1;
   /* Logically, these two would go in a theoretical base shared by var and
      parm decl. */
-  unsigned gimple_reg_flag : 1;
+  unsigned not_gimple_reg_flag : 1;
   /* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_BY_REFERENCE.  */
   unsigned decl_by_reference_flag : 1;
   /* In a VAR_DECL and PARM_DECL, this is DECL_READ_P.  */
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 2a409dcaffe..10ef2e3157c 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2072,9 +2072,6 @@  lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
 	  gimple_set_location (s, gimple_location (stmt));
 	  gimple_set_block (s, gimple_block (stmt));
 	  gimple_set_lhs (stmt, tmp);
-	  if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
-	      || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
-	    DECL_GIMPLE_REG_P (tmp) = 1;
 	  gsi_insert_after (gsi, s, GSI_SAME_STMT);
 	}
       /* Look for things that can throw exceptions, and record them.  */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 69ca8e99109..b4a69c1ad48 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3670,11 +3670,9 @@  declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 	  if (TREE_ADDRESSABLE (result))
 	    mark_addressable (var);
 	}
-      if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
-           || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE)
-	  && !DECL_GIMPLE_REG_P (result)
+      if (DECL_NOT_GIMPLE_REG_P (result)
 	  && DECL_P (var))
-	DECL_GIMPLE_REG_P (var) = 0;
+	DECL_NOT_GIMPLE_REG_P (var) = 1;
 
       if (!useless_type_conversion_p (callee_type, caller_type))
 	var = build1 (VIEW_CONVERT_EXPR, callee_type, var);
@@ -3717,10 +3715,8 @@  declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 	    use_it = false;
 	  else if (is_global_var (base_m))
 	    use_it = false;
-	  else if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
-		    || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE)
-		   && !DECL_GIMPLE_REG_P (result)
-		   && DECL_GIMPLE_REG_P (base_m))
+	  else if (DECL_NOT_GIMPLE_REG_P (result)
+		   && !DECL_NOT_GIMPLE_REG_P (base_m))
 	    use_it = false;
 	  else if (!TREE_ADDRESSABLE (base_m))
 	    use_it = true;
@@ -3760,11 +3756,8 @@  declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 	     to using a MEM_REF to not leak invalid GIMPLE to the following
 	     passes.  */
 	  /* Prevent var from being written into SSA form.  */
-	  if (TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
-	      || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE)
-	    DECL_GIMPLE_REG_P (var) = false;
-	  else if (is_gimple_reg_type (TREE_TYPE (var)))
-	    TREE_ADDRESSABLE (var) = true;
+	  if (is_gimple_reg_type (TREE_TYPE (var)))
+	    DECL_NOT_GIMPLE_REG_P (var) = true;
 	  use = fold_build2 (MEM_REF, caller_type,
 			     build_fold_addr_expr (var),
 			     build_int_cst (ptr_type_node, 0));
@@ -5930,7 +5923,7 @@  copy_decl_to_var (tree decl, copy_body_data *id)
   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
   TREE_READONLY (copy) = TREE_READONLY (decl);
   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
-  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
+  DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
   DECL_BY_REFERENCE (copy) = DECL_BY_REFERENCE (decl);
 
   return copy_decl_for_dup_finish (id, decl, copy);
@@ -5960,7 +5953,7 @@  copy_result_decl_to_var (tree decl, copy_body_data *id)
   if (!DECL_BY_REFERENCE (decl))
     {
       TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
-      DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
+      DECL_NOT_GIMPLE_REG_P (copy) = DECL_NOT_GIMPLE_REG_P (decl);
     }
 
   return copy_decl_for_dup_finish (id, decl, copy);
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 6528acac31a..c24931effac 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -2430,8 +2430,7 @@  pass_build_ssa::execute (function *fun)
   basic_block bb;
 
   /* Increase the set of variables we can rewrite into SSA form
-     by clearing TREE_ADDRESSABLE and setting DECL_GIMPLE_REG_P
-     and transform the IL to support this.  */
+     by clearing TREE_ADDRESSABLE and transform the IL to support this.  */
   if (optimize)
     execute_update_addresses_taken ();
 
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 6f696da5332..de168df70a1 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -160,9 +160,6 @@  create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
   DECL_CONTEXT (tmp_var) = info->context;
   DECL_CHAIN (tmp_var) = info->new_local_var_chain;
   DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
-  if (TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (tmp_var) = 1;
 
   info->new_local_var_chain = tmp_var;
 
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index d9250d36c72..8cd50234a1c 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1574,7 +1574,7 @@  separate_decls_in_region_name (tree name, name_to_copy_table_type *name_copies,
   if (!dslot->to)
     {
       var_copy = create_tmp_var (TREE_TYPE (var), get_name (var));
-      DECL_GIMPLE_REG_P (var_copy) = DECL_GIMPLE_REG_P (var);
+      DECL_NOT_GIMPLE_REG_P (var_copy) = DECL_NOT_GIMPLE_REG_P (var);
       dslot->uid = uid;
       dslot->to = var_copy;
 
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 227bde06257..4793b48f32c 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -2168,15 +2168,9 @@  create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
        variant.  This avoids issues with weirdo ABIs like AAPCS.  */
     repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT (type),
 						 TYPE_QUALS (type)), "SR");
-  if (TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    {
-      if (!access->grp_partial_lhs)
-	DECL_GIMPLE_REG_P (repl) = 1;
-    }
-  else if (access->grp_partial_lhs
-	   && is_gimple_reg_type (type))
-    TREE_ADDRESSABLE (repl) = 1;
+  if (access->grp_partial_lhs
+      && is_gimple_reg_type (type))
+    DECL_NOT_GIMPLE_REG_P (repl) = 1;
 
   DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
   DECL_ARTIFICIAL (repl) = 1;
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 1a50045b367..b68da91723b 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2945,6 +2945,8 @@  pass_forwprop::execute (function *fun)
 		      != TARGET_MEM_REF))
 		{
 		  tree use_lhs = gimple_assign_lhs (use_stmt);
+		  if (auto_var_p (use_lhs))
+		    DECL_NOT_GIMPLE_REG_P (use_lhs) = 1;
 		  tree new_lhs = build1 (REALPART_EXPR,
 					 TREE_TYPE (TREE_TYPE (use_lhs)),
 					 unshare_expr (use_lhs));
@@ -2996,6 +2998,9 @@  pass_forwprop::execute (function *fun)
 		    = tree_to_uhwi (TYPE_SIZE (elt_t));
 		  unsigned HOST_WIDE_INT n
 		    = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs)));
+		  tree use_lhs = gimple_assign_lhs (use_stmt);
+		  if (auto_var_p (use_lhs))
+		    DECL_NOT_GIMPLE_REG_P (use_lhs) = 1;
 		  for (unsigned HOST_WIDE_INT bi = 0; bi < n; bi += elt_w)
 		    {
 		      unsigned HOST_WIDE_INT ci = bi / elt_w;
@@ -3004,7 +3009,6 @@  pass_forwprop::execute (function *fun)
 			new_rhs = CONSTRUCTOR_ELT (rhs, ci)->value;
 		      else
 			new_rhs = build_zero_cst (elt_t);
-		      tree use_lhs = gimple_assign_lhs (use_stmt);
 		      tree new_lhs = build3 (BIT_FIELD_REF,
 					     elt_t,
 					     unshare_expr (use_lhs),
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 4f4ab2b8992..c47b963bbb2 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1583,8 +1583,8 @@  non_rewritable_lvalue_p (tree lhs)
   return true;
 }
 
-/* When possible, clear TREE_ADDRESSABLE bit or set DECL_GIMPLE_REG_P bit and
-   mark the variable VAR for conversion into SSA.  Return true when updating
+/* When possible, clear TREE_ADDRESSABLE bit, set or clear DECL_NOT_GIMPLE_REG_P
+   and mark the variable VAR for conversion into SSA.  Return true when updating
    stmts is required.  */
 
 static void
@@ -1597,24 +1597,11 @@  maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs,
       || bitmap_bit_p (addresses_taken, DECL_UID (var)))
     return;
 
-  if (TREE_ADDRESSABLE (var)
-      /* Do not change TREE_ADDRESSABLE if we need to preserve var as
-	 a non-register.  Otherwise we are confused and forget to
-	 add virtual operands for it.  */
-      && (!is_gimple_reg_type (TREE_TYPE (var))
-	  || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
-	  || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
-	  || !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
+  bool maybe_reg = false;
+  if (TREE_ADDRESSABLE (var))
     {
       TREE_ADDRESSABLE (var) = 0;
-      /* If we cleared TREE_ADDRESSABLE make sure DECL_GIMPLE_REG_P
-         is unset if we cannot rewrite the var into SSA.  */
-      if ((TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
-	   || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE)
-	  && bitmap_bit_p (not_reg_needs, DECL_UID (var)))
-	DECL_GIMPLE_REG_P (var) = 0;
-      if (is_gimple_reg (var))
-	bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
+      maybe_reg = true;
       if (dump_file)
 	{
 	  fprintf (dump_file, "No longer having address taken: ");
@@ -1623,20 +1610,36 @@  maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs,
 	}
     }
 
-  if (!DECL_GIMPLE_REG_P (var)
-      && !bitmap_bit_p (not_reg_needs, DECL_UID (var))
-      && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
-	  || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE)
-      && !TREE_THIS_VOLATILE (var)
-      && (!VAR_P (var) || !DECL_HARD_REGISTER (var)))
+  /* For register type decls if we do not have any partial defs
+     we cannot express in SSA form mark them as DECL_NOT_GIMPLE_REG_P
+     as to avoid SSA rewrite.  For the others go ahead and mark
+     them for renaming.  */
+  if (is_gimple_reg_type (TREE_TYPE (var)))
     {
-      DECL_GIMPLE_REG_P (var) = 1;
-      bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
-      if (dump_file)
+      if (bitmap_bit_p (not_reg_needs, DECL_UID (var)))
 	{
-	  fprintf (dump_file, "Now a gimple register: ");
-	  print_generic_expr (dump_file, var);
-	  fprintf (dump_file, "\n");
+	  DECL_NOT_GIMPLE_REG_P (var) = 1;
+	  if (dump_file)
+	    {
+	      fprintf (dump_file, "Has partial defs: ");
+	      print_generic_expr (dump_file, var);
+	      fprintf (dump_file, "\n");
+	    }
+	}
+      else if (DECL_NOT_GIMPLE_REG_P (var))
+	{
+	  maybe_reg = true;
+	  DECL_NOT_GIMPLE_REG_P (var) = 0;
+	}
+      if (maybe_reg && is_gimple_reg (var))
+	{
+	  if (dump_file)
+	    {
+	      fprintf (dump_file, "Now a gimple register: ");
+	      print_generic_expr (dump_file, var);
+	      fprintf (dump_file, "\n");
+	    }
+	  bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
 	}
     }
 }
@@ -1669,7 +1672,8 @@  is_asan_mark_p (gimple *stmt)
   return false;
 }
 
-/* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables.  */
+/* Compute TREE_ADDRESSABLE and whether we have unhandled partial defs
+   for local variables.  */
 
 void
 execute_update_addresses_taken (void)
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 0bfc272d076..79b97ffa9a3 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -236,7 +236,7 @@  unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
   DECL_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_PRESERVE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_EXTERNAL (expr) = (unsigned) bp_unpack_value (bp, 1);
-  DECL_GIMPLE_REG_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+  DECL_NOT_GIMPLE_REG_P (expr) = (unsigned) bp_unpack_value (bp, 1);
   SET_DECL_ALIGN (expr, (unsigned) bp_unpack_var_len_unsigned (bp));
 #ifdef ACCEL_COMPILER
   if (DECL_ALIGN (expr) > targetm.absolute_biggest_alignment)
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 5bbcebba87e..3ab8c889a23 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -201,7 +201,7 @@  pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
   bp_pack_value (bp, DECL_USER_ALIGN (expr), 1);
   bp_pack_value (bp, DECL_PRESERVE_P (expr), 1);
   bp_pack_value (bp, DECL_EXTERNAL (expr), 1);
-  bp_pack_value (bp, DECL_GIMPLE_REG_P (expr), 1);
+  bp_pack_value (bp, DECL_NOT_GIMPLE_REG_P (expr), 1);
   bp_pack_var_len_unsigned (bp, DECL_ALIGN (expr));
 
   if (TREE_CODE (expr) == LABEL_DECL)
diff --git a/gcc/tree.h b/gcc/tree.h
index 1c28785d411..66042c14290 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2646,8 +2646,8 @@  extern machine_mode vector_type_mode (const_tree);
    they are killing assignments.  Thus the variable may now
    be treated as a GIMPLE register, and use real instead of
    virtual ops in SSA form.  */
-#define DECL_GIMPLE_REG_P(DECL) \
-  DECL_COMMON_CHECK (DECL)->decl_common.gimple_reg_flag
+#define DECL_NOT_GIMPLE_REG_P(DECL) \
+  DECL_COMMON_CHECK (DECL)->decl_common.not_gimple_reg_flag
 
 extern tree decl_value_expr_lookup (tree);
 extern void decl_value_expr_insert (tree, tree);