public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Qing Zhao <qing.zhao@oracle.com>
To: Richard Biener <rguenther@suse.de>,
	Martin Jambor <mjambor@suse.cz>, Jakub Jelinek <jakub@redhat.com>
Cc: Kees Cook <keescook@chromium.org>,
	Nick Alcock via Gcc-patches <gcc-patches@gcc.gnu.org>,
	Richard Biener <richard.guenther@gmail.com>
Subject: [patch][version 6] add -ftrivial-auto-var-init and variable attribute "uninitialized" to gcc
Date: Tue, 27 Jul 2021 03:26:00 +0000	[thread overview]
Message-ID: <52E29277-1403-4755-901A-528116C43FB8@oracle.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 10350 bytes --]

Hi,

This is the 6th version of the patch for the new security feature for GCC.

I have tested it with bootstrap on both x86 and aarch64, regression testing on both x86 and aarch64.
Also compile CPU2017 (running is ongoing), without any issue. (With the fix to bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101586).

Please take a look and let me know any issue.

Thanks

Qing

******Compared with the 5th version, the changes are:

 1. Fix two issues raised by Martin Jambor in tree-sra.c:

   A. Inside "scan_function", Do not set cannot_scalarize_away_bitmap for a call to DEFERRED_INIT.
   B. Fix a potential issue for single-field structure.

 2. Add two testing cases based on gcc/testsuite/gcc.dg/tree-ssa/sra-12.c to verity SRA total scalarization will not be confused by auto initializatoin.

******the 5th version compared with the 4th version, the following are the major changes:

1. delete the code for handling "grp_to_be_debug_replaced" since they are not needed per Martin Jambor's suggestion.
2. for Pattern init, call __builtin_clear_padding after the call to .DEFERRED_INIT to initialize the paddings to zeroes;
3. for partially or fully initialized auto variables, call   __builtin_clear_padding before the real initialization to initialize
   the paddings to zeroes.
4. Update the documentation with padding initialization to zeroes.
5. in order to reuse __builtin_clear_padding for auto init purpose, add one more dummy argument to indiciate whether it's for auto init or not,
  if for auto init, do not emit error messages to avoid confusing users.
6. Add new testing cases to verify padding initializations.
7. rename some of the old testing cases to make the file name reflecting the testing purpose per Kees Cook's suggestions.

******Please see version 5 at:
https://gcc.gnu.org/pipermail/gcc-patches/2021-July/575977.html

******ChangeLog is:

gcc/ChangeLog:

2021-07-26  qing zhao  <qing.zhao@oracle.com>

        * builtins.c (expand_builtin_memset): Make external visible.
        * builtins.h (expand_builtin_memset): Declare extern.
        * common.opt (ftrivial-auto-var-init=): New option.
        * doc/extend.texi: Document the uninitialized attribute.
        * doc/invoke.texi: Document -ftrivial-auto-var-init.
        * flag-types.h (enum auto_init_type): New enumerated type
        auto_init_type.
        * gimple-fold.c (clear_padding_type): Add one new parameter.
        (clear_padding_union): Likewise.
        (clear_padding_emit_loop): Likewise.
        (clear_type_padding_in_mask): Likewise.
        (gimple_fold_builtin_clear_padding): Handle this new parameter.
        * gimplify.c (gimple_add_init_for_auto_var): New function.
        (maybe_with_size_expr): Forword declaration.
        (build_deferred_init): New function.
        (gimple_add_padding_init_for_auto_var): New function.
        (gimplify_decl_expr): Add initialization to automatic variables per
        users' requests.
        (gimplify_call_expr): Add one new parameter for call to
        __builtin_clear_padding.
        (gimplify_modify_expr_rhs): Add padding initialization before
        gimplify_init_constructor.
        * internal-fn.c (INIT_PATTERN_VALUE): New macro.
        (expand_DEFERRED_INIT): New function.
        * internal-fn.def (DEFERRED_INIT): New internal function.
        * tree-cfg.c (verify_gimple_call): Verify calls to .DEFERRED_INIT.
        * tree-sra.c (generate_subtree_deferred_init): New function.
        (scan_function): Avoid setting cannot_scalarize_away_bitmap for
        calls to .DEFERRED_INIT.
        (sra_modify_deferred_init): New function.
        (sra_modify_function_body): Handle calls to DEFERRED_INIT specially.
        * tree-ssa-structalias.c (find_func_aliases_for_call): Likewise.
        * tree-ssa-uninit.c (warn_uninit): Handle calls to DEFERRED_INIT
        specially.
        (check_defs): Likewise.
        (warn_uninitialized_vars): Likewise.
        * tree-ssa.c (ssa_undefined_value_p): Likewise.

gcc/c-family/ChangeLog:

2021-07-26  qing zhao  <qing.zhao@oracle.com>

        * c-attribs.c (handle_uninitialized_attribute): New function.
        (c_common_attribute_table): Add "uninitialized" attribute.

gcc/testsuite/ChangeLog:


2021-07-26  qing zhao  <qing.zhao@oracle.com>

        * c-c++-common/auto-init-1.c: New test.
        * c-c++-common/auto-init-10.c: New test.
        * c-c++-common/auto-init-11.c: New test.
        * c-c++-common/auto-init-12.c: New test.
        * c-c++-common/auto-init-13.c: New test.
        * c-c++-common/auto-init-14.c: New test.
        * c-c++-common/auto-init-15.c: New test.
        * c-c++-common/auto-init-16.c: New test.
        * c-c++-common/auto-init-2.c: New test.
        * c-c++-common/auto-init-3.c: New test.
        * c-c++-common/auto-init-4.c: New test.
        * c-c++-common/auto-init-5.c: New test.
        * c-c++-common/auto-init-6.c: New test.
        * c-c++-common/auto-init-7.c: New test.
        * c-c++-common/auto-init-8.c: New test.
        * c-c++-common/auto-init-9.c: New test.
        * c-c++-common/auto-init-esra.c: New test.
        * c-c++-common/auto-init-padding-1.c: New test.
        * c-c++-common/auto-init-padding-2.c: New test.
        * c-c++-common/auto-init-padding-3.c: New test.
        * g++.dg/auto-init-uninit-pred-1_a.C: New test.
        * g++.dg/auto-init-uninit-pred-1_b.C: New test.
        * g++.dg/auto-init-uninit-pred-2_a.C: New test.
        * g++.dg/auto-init-uninit-pred-2_b.C: New test.
        * g++.dg/auto-init-uninit-pred-3_a.C: New test.
        * g++.dg/auto-init-uninit-pred-3_b.C: New test.
        * g++.dg/auto-init-uninit-pred-4.C: New test.
        * g++.dg/auto-init-uninit-pred-loop-1_a.cc: New test.
        * g++.dg/auto-init-uninit-pred-loop-1_b.cc: New test.
        * g++.dg/auto-init-uninit-pred-loop-1_c.cc: New test.
        * g++.dg/auto-init-uninit-pred-loop_1.cc: New test.
        * gcc.dg/auto-init-sra-1.c: New test.
        * gcc.dg/auto-init-sra-2.c: New test.
        * gcc.dg/auto-init-uninit-1.c: New test.
        * gcc.dg/auto-init-uninit-11.c: New test.
        * gcc.dg/auto-init-uninit-12.c: New test.
        * gcc.dg/auto-init-uninit-13.c: New test.
        * gcc.dg/auto-init-uninit-14.c: New test.
        * gcc.dg/auto-init-uninit-15.c: New test.
        * gcc.dg/auto-init-uninit-16.c: New test.
        * gcc.dg/auto-init-uninit-17.c: New test.
        * gcc.dg/auto-init-uninit-18.c: New test.
        * gcc.dg/auto-init-uninit-19.c: New test.
        * gcc.dg/auto-init-uninit-2.c: New test.
        * gcc.dg/auto-init-uninit-20.c: New test.
        * gcc.dg/auto-init-uninit-21.c: New test.
        * gcc.dg/auto-init-uninit-22.c: New test.
        * gcc.dg/auto-init-uninit-23.c: New test.
        * gcc.dg/auto-init-uninit-24.c: New test.
        * gcc.dg/auto-init-uninit-25.c: New test.
        * gcc.dg/auto-init-uninit-26.c: New test.
        * gcc.dg/auto-init-uninit-3.c: New test.
        * gcc.dg/auto-init-uninit-34.c: New test.
        * gcc.dg/auto-init-uninit-36.c: New test.
        * gcc.dg/auto-init-uninit-37.c: New test.
        * gcc.dg/auto-init-uninit-4.c: New test.
        * gcc.dg/auto-init-uninit-5.c: New test.
        * gcc.dg/auto-init-uninit-6.c: New test.
        * gcc.dg/auto-init-uninit-8.c: New test.
        * gcc.dg/auto-init-uninit-9.c: New test.
        * gcc.dg/auto-init-uninit-A.c: New test.
        * gcc.dg/auto-init-uninit-B.c: New test.
        * gcc.dg/auto-init-uninit-C.c: New test.
        * gcc.dg/auto-init-uninit-H.c: New test.
        * gcc.dg/auto-init-uninit-I.c: New test.
        * gcc.target/aarch64/auto-init-1.c: New test.
        * gcc.target/aarch64/auto-init-2.c: New test.
        * gcc.target/aarch64/auto-init-3.c: New test.
        * gcc.target/aarch64/auto-init-4.c: New test.
        * gcc.target/aarch64/auto-init-5.c: New test.
        * gcc.target/aarch64/auto-init-6.c: New test.
        * gcc.target/aarch64/auto-init-7.c: New test.
        * gcc.target/aarch64/auto-init-8.c: New test.
        * gcc.target/aarch64/auto-init-padding-1.c: New test.
        * gcc.target/aarch64/auto-init-padding-10.c: New test.
        * gcc.target/aarch64/auto-init-padding-11.c: New test.
        * gcc.target/aarch64/auto-init-padding-12.c: New test.
        * gcc.target/aarch64/auto-init-padding-2.c: New test.
        * gcc.target/aarch64/auto-init-padding-3.c: New test.
        * gcc.target/aarch64/auto-init-padding-4.c: New test.
        * gcc.target/aarch64/auto-init-padding-5.c: New test.
        * gcc.target/aarch64/auto-init-padding-6.c: New test.
        * gcc.target/aarch64/auto-init-padding-7.c: New test.
        * gcc.target/aarch64/auto-init-padding-8.c: New test.
        * gcc.target/aarch64/auto-init-padding-9.c: New test.
        * gcc.target/i386/auto-init-1.c: New test.
        * gcc.target/i386/auto-init-2.c: New test.
        * gcc.target/i386/auto-init-21.c: New test.
        * gcc.target/i386/auto-init-22.c: New test.
        * gcc.target/i386/auto-init-23.c: New test.
        * gcc.target/i386/auto-init-24.c: New test.
        * gcc.target/i386/auto-init-3.c: New test.
        * gcc.target/i386/auto-init-4.c: New test.
        * gcc.target/i386/auto-init-5.c: New test.
        * gcc.target/i386/auto-init-6.c: New test.
        * gcc.target/i386/auto-init-7.c: New test.
        * gcc.target/i386/auto-init-8.c: New test.
        * gcc.target/i386/auto-init-padding-1.c: New test.
        * gcc.target/i386/auto-init-padding-10.c: New test.
        * gcc.target/i386/auto-init-padding-11.c: New test.
        * gcc.target/i386/auto-init-padding-12.c: New test.
        * gcc.target/i386/auto-init-padding-2.c: New test.
        * gcc.target/i386/auto-init-padding-3.c: New test.
        * gcc.target/i386/auto-init-padding-4.c: New test.
        * gcc.target/i386/auto-init-padding-5.c: New test.
        * gcc.target/i386/auto-init-padding-6.c: New test.
        * gcc.target/i386/auto-init-padding-7.c: New test.
        * gcc.target/i386/auto-init-padding-8.c: New test.
        * gcc.target/i386/auto-init-padding-9.c: New test.

******The complete 6th version of the patch is:



[-- Attachment #2: 0001-the-6th-version.patch --]
[-- Type: application/octet-stream, Size: 170515 bytes --]

From a894af20c1505ccabd7da7ae1e37171c54c94072 Mon Sep 17 00:00:00 2001
From: Qing Zhao <qing.zhao@oracle.com>
Date: Tue, 20 Jul 2021 19:43:13 +0000
Subject: [PATCH] the 6th version

---
 gcc/builtins.c                                |   3 +-
 gcc/builtins.h                                |   1 +
 gcc/c-family/c-attribs.c                      |  19 ++
 gcc/common.opt                                |  16 ++
 gcc/doc/extend.texi                           |  16 ++
 gcc/doc/invoke.texi                           |  41 ++-
 gcc/flag-types.h                              |   7 +
 gcc/gimple-fold.c                             |  48 ++--
 gcc/gimplify.c                                | 162 +++++++++++-
 gcc/internal-fn.c                             | 108 ++++++++
 gcc/internal-fn.def                           |   5 +
 gcc/testsuite/c-c++-common/auto-init-1.c      |  39 +++
 gcc/testsuite/c-c++-common/auto-init-10.c     |  17 ++
 gcc/testsuite/c-c++-common/auto-init-11.c     |  14 ++
 gcc/testsuite/c-c++-common/auto-init-12.c     |  14 ++
 gcc/testsuite/c-c++-common/auto-init-13.c     |  23 ++
 gcc/testsuite/c-c++-common/auto-init-14.c     |  23 ++
 gcc/testsuite/c-c++-common/auto-init-15.c     |  13 +
 gcc/testsuite/c-c++-common/auto-init-16.c     |  13 +
 gcc/testsuite/c-c++-common/auto-init-2.c      |  39 +++
 gcc/testsuite/c-c++-common/auto-init-3.c      |  19 ++
 gcc/testsuite/c-c++-common/auto-init-4.c      |  19 ++
 gcc/testsuite/c-c++-common/auto-init-5.c      |  21 ++
 gcc/testsuite/c-c++-common/auto-init-6.c      |  21 ++
 gcc/testsuite/c-c++-common/auto-init-7.c      |  35 +++
 gcc/testsuite/c-c++-common/auto-init-8.c      |  35 +++
 gcc/testsuite/c-c++-common/auto-init-9.c      |  17 ++
 gcc/testsuite/c-c++-common/auto-init-esra.c   |  35 +++
 .../c-c++-common/auto-init-padding-1.c        |  23 ++
 .../c-c++-common/auto-init-padding-2.c        | 114 +++++++++
 .../c-c++-common/auto-init-padding-3.c        | 114 +++++++++
 .../g++.dg/auto-init-uninit-pred-1_a.C        |  63 +++++
 .../g++.dg/auto-init-uninit-pred-1_b.C        |  63 +++++
 .../g++.dg/auto-init-uninit-pred-2_a.C        |  62 +++++
 .../g++.dg/auto-init-uninit-pred-2_b.C        |  62 +++++
 .../g++.dg/auto-init-uninit-pred-3_a.C        |  77 ++++++
 .../g++.dg/auto-init-uninit-pred-3_b.C        |  87 +++++++
 .../g++.dg/auto-init-uninit-pred-4.C          |  16 ++
 .../g++.dg/auto-init-uninit-pred-loop-1_a.cc  |  21 ++
 .../g++.dg/auto-init-uninit-pred-loop-1_b.cc  |  21 ++
 .../g++.dg/auto-init-uninit-pred-loop-1_c.cc  |  23 ++
 .../g++.dg/auto-init-uninit-pred-loop_1.cc    |  21 ++
 gcc/testsuite/gcc.dg/auto-init-sra-1.c        |  24 ++
 gcc/testsuite/gcc.dg/auto-init-sra-2.c        |  24 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-1.c     |  30 +++
 gcc/testsuite/gcc.dg/auto-init-uninit-11.c    |  42 ++++
 gcc/testsuite/gcc.dg/auto-init-uninit-12.c    |  12 +
 gcc/testsuite/gcc.dg/auto-init-uninit-13.c    |  10 +
 gcc/testsuite/gcc.dg/auto-init-uninit-14.c    |  20 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-15.c    |  26 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-16.c    |  23 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-17.c    |  15 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-18.c    |  24 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-19.c    |  26 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-2.c     |  52 ++++
 gcc/testsuite/gcc.dg/auto-init-uninit-20.c    |  18 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-21.c    |  33 +++
 gcc/testsuite/gcc.dg/auto-init-uninit-22.c    |  69 +++++
 gcc/testsuite/gcc.dg/auto-init-uninit-23.c    |  27 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-24.c    |  10 +
 gcc/testsuite/gcc.dg/auto-init-uninit-25.c    |  23 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-26.c    |  23 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-3.c     |  33 +++
 gcc/testsuite/gcc.dg/auto-init-uninit-34.c    |  58 +++++
 gcc/testsuite/gcc.dg/auto-init-uninit-36.c    | 238 ++++++++++++++++++
 gcc/testsuite/gcc.dg/auto-init-uninit-37.c    | 154 ++++++++++++
 gcc/testsuite/gcc.dg/auto-init-uninit-4.c     |  52 ++++
 gcc/testsuite/gcc.dg/auto-init-uninit-5.c     |  39 +++
 gcc/testsuite/gcc.dg/auto-init-uninit-6.c     |  47 ++++
 gcc/testsuite/gcc.dg/auto-init-uninit-8.c     |  32 +++
 gcc/testsuite/gcc.dg/auto-init-uninit-9.c     |  42 ++++
 gcc/testsuite/gcc.dg/auto-init-uninit-A.c     | 117 +++++++++
 gcc/testsuite/gcc.dg/auto-init-uninit-B.c     |  15 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-C.c     |  21 ++
 gcc/testsuite/gcc.dg/auto-init-uninit-H.c     |  33 +++
 gcc/testsuite/gcc.dg/auto-init-uninit-I.c     |   8 +
 .../gcc.target/aarch64/auto-init-1.c          |  32 +++
 .../gcc.target/aarch64/auto-init-2.c          |  35 +++
 .../gcc.target/aarch64/auto-init-3.c          |  17 ++
 .../gcc.target/aarch64/auto-init-4.c          |  19 ++
 .../gcc.target/aarch64/auto-init-5.c          |  19 ++
 .../gcc.target/aarch64/auto-init-6.c          |  18 ++
 .../gcc.target/aarch64/auto-init-7.c          |  32 +++
 .../gcc.target/aarch64/auto-init-8.c          |  32 +++
 .../gcc.target/aarch64/auto-init-padding-1.c  |  17 ++
 .../gcc.target/aarch64/auto-init-padding-10.c |  22 ++
 .../gcc.target/aarch64/auto-init-padding-11.c |  27 ++
 .../gcc.target/aarch64/auto-init-padding-12.c |  27 ++
 .../gcc.target/aarch64/auto-init-padding-2.c  |  18 ++
 .../gcc.target/aarch64/auto-init-padding-3.c  |  27 ++
 .../gcc.target/aarch64/auto-init-padding-4.c  |  27 ++
 .../gcc.target/aarch64/auto-init-padding-5.c  |  22 ++
 .../gcc.target/aarch64/auto-init-padding-6.c  |  20 ++
 .../gcc.target/aarch64/auto-init-padding-7.c  |  20 ++
 .../gcc.target/aarch64/auto-init-padding-8.c  |  22 ++
 .../gcc.target/aarch64/auto-init-padding-9.c  |  21 ++
 gcc/testsuite/gcc.target/i386/auto-init-1.c   |  32 +++
 gcc/testsuite/gcc.target/i386/auto-init-2.c   |  36 +++
 gcc/testsuite/gcc.target/i386/auto-init-21.c  |  14 ++
 gcc/testsuite/gcc.target/i386/auto-init-22.c  |  14 ++
 gcc/testsuite/gcc.target/i386/auto-init-23.c  |  13 +
 gcc/testsuite/gcc.target/i386/auto-init-24.c  |  13 +
 gcc/testsuite/gcc.target/i386/auto-init-3.c   |  17 ++
 gcc/testsuite/gcc.target/i386/auto-init-4.c   |  20 ++
 gcc/testsuite/gcc.target/i386/auto-init-5.c   |  20 ++
 gcc/testsuite/gcc.target/i386/auto-init-6.c   |  19 ++
 gcc/testsuite/gcc.target/i386/auto-init-7.c   |  32 +++
 gcc/testsuite/gcc.target/i386/auto-init-8.c   |  35 +++
 .../gcc.target/i386/auto-init-padding-1.c     |  19 ++
 .../gcc.target/i386/auto-init-padding-10.c    |  21 ++
 .../gcc.target/i386/auto-init-padding-11.c    |  26 ++
 .../gcc.target/i386/auto-init-padding-12.c    |  26 ++
 .../gcc.target/i386/auto-init-padding-2.c     |  19 ++
 .../gcc.target/i386/auto-init-padding-3.c     |  30 +++
 .../gcc.target/i386/auto-init-padding-4.c     |  28 +++
 .../gcc.target/i386/auto-init-padding-5.c     |  22 ++
 .../gcc.target/i386/auto-init-padding-6.c     |  22 ++
 .../gcc.target/i386/auto-init-padding-7.c     |  22 ++
 .../gcc.target/i386/auto-init-padding-8.c     |  22 ++
 .../gcc.target/i386/auto-init-padding-9.c     |  23 ++
 gcc/tree-cfg.c                                |  99 ++++++--
 gcc/tree-sra.c                                | 124 ++++++++-
 gcc/tree-ssa-structalias.c                    |   3 +
 gcc/tree-ssa-uninit.c                         |  47 ++++
 gcc/tree-ssa.c                                |  40 +++
 125 files changed, 4286 insertions(+), 56 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-1.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-10.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-11.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-12.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-13.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-14.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-15.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-16.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-2.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-3.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-4.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-5.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-6.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-7.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-8.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-9.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-esra.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-padding-1.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-padding-2.c
 create mode 100644 gcc/testsuite/c-c++-common/auto-init-padding-3.c
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-1_b.C
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-2_b.C
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-3_b.C
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_a.cc
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_b.cc
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_c.cc
 create mode 100644 gcc/testsuite/g++.dg/auto-init-uninit-pred-loop_1.cc
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-sra-1.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-sra-2.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-1.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-11.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-12.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-13.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-14.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-15.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-16.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-17.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-18.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-19.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-2.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-20.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-21.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-22.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-23.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-24.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-25.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-26.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-3.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-34.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-36.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-37.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-4.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-5.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-6.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-8.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-9.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-A.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-B.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-C.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-H.c
 create mode 100644 gcc/testsuite/gcc.dg/auto-init-uninit-I.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-3.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-4.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-5.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-6.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-7.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-8.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-10.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-11.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-12.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-3.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-4.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-5.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-6.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-7.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-8.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/auto-init-padding-9.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-21.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-22.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-23.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-24.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-5.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-6.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-7.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-8.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-10.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-11.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-12.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-5.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-6.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-7.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-8.c
 create mode 100644 gcc/testsuite/gcc.target/i386/auto-init-padding-9.c

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 39ab139b7e1c..aa8e3e499e48 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -145,7 +145,6 @@ static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
 static rtx expand_builtin_stpncpy (tree, rtx);
 static rtx expand_builtin_strncat (tree, rtx);
 static rtx expand_builtin_strncpy (tree, rtx);
-static rtx expand_builtin_memset (tree, rtx, machine_mode);
 static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
 static rtx expand_builtin_bzero (tree);
 static rtx expand_builtin_strlen (tree, rtx, machine_mode);
@@ -6757,7 +6756,7 @@ builtin_memset_gen_str (void *data, void *prevp,
    try to get the result in TARGET, if convenient (and in mode MODE if that's
    convenient).  */
 
-static rtx
+rtx
 expand_builtin_memset (tree exp, rtx target, machine_mode mode)
 {
   if (!validate_arglist (exp,
diff --git a/gcc/builtins.h b/gcc/builtins.h
index a64ece3f1cd9..b18fe079ec3a 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -114,6 +114,7 @@ extern rtx builtin_strncpy_read_str (void *, void *, HOST_WIDE_INT,
 				     scalar_int_mode);
 extern rtx builtin_memset_read_str (void *, void *, HOST_WIDE_INT,
 				    scalar_int_mode);
+extern rtx expand_builtin_memset (tree, rtx, machine_mode);
 extern rtx expand_builtin_saveregs (void);
 extern tree std_build_builtin_va_list (void);
 extern tree std_fn_abi_va_list (tree);
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index e60fb31d8c8e..9b594006fe44 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -83,6 +83,7 @@ static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
 static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
 static tree handle_error_attribute (tree *, tree, tree, int, bool *);
 static tree handle_used_attribute (tree *, tree, tree, int, bool *);
+static tree handle_uninitialized_attribute (tree *, tree, tree, int, bool *);
 static tree handle_externally_visible_attribute (tree *, tree, tree, int,
 						 bool *);
 static tree handle_no_reorder_attribute (tree *, tree, tree, int,
@@ -331,6 +332,8 @@ const struct attribute_spec c_common_attribute_table[] =
 			      handle_used_attribute, NULL },
   { "unused",                 0, 0, false, false, false, false,
 			      handle_unused_attribute, NULL },
+  { "uninitialized",	      0, 0, true, false, false, false,
+			      handle_uninitialized_attribute, NULL },
   { "retain",                 0, 0, true,  false, false, false,
 			      handle_retain_attribute, NULL },
   { "externally_visible",     0, 0, true,  false, false, false,
@@ -1613,6 +1616,22 @@ handle_retain_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
   return NULL_TREE;
 }
 
+/* Handle an "uninitialized" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_uninitialized_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+				int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (!VAR_P (*node))
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "externally_visible" attribute; arguments as in
    struct attribute_spec.handler.  */
 
diff --git a/gcc/common.opt b/gcc/common.opt
index d9da1131edaa..5e4221e8af64 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3078,6 +3078,22 @@ ftree-scev-cprop
 Common Var(flag_tree_scev_cprop) Init(1) Optimization
 Enable copy propagation of scalar-evolution information.
 
+ftrivial-auto-var-init=
+Common Joined RejectNegative Enum(auto_init_type) Var(flag_auto_var_init) Init(AUTO_INIT_UNINITIALIZED) Optimization
+-ftrivial-auto-var-init=[uninitialized|pattern|zero]	Add initializations to automatic variables.
+
+Enum
+Name(auto_init_type) Type(enum auto_init_type) UnknownError(unrecognized automatic variable initialization type %qs)
+
+EnumValue
+Enum(auto_init_type) String(uninitialized) Value(AUTO_INIT_UNINITIALIZED)
+
+EnumValue
+Enum(auto_init_type) String(pattern) Value(AUTO_INIT_PATTERN)
+
+EnumValue
+Enum(auto_init_type) String(zero) Value(AUTO_INIT_ZERO)
+
 ; -fverbose-asm causes extra commentary information to be produced in
 ; the generated assembly code (to make it more readable).  This option
 ; is generally only of use to those who actually need to read the
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index b83cd4919bb1..54ee99d29407 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -7540,6 +7540,22 @@ will be placed in new, unique sections.
 
 This additional functionality requires Binutils version 2.36 or later.
 
+@item uninitialized
+@cindex @code{uninitialized} variable attribute
+This attribute, attached to a variable with automatic storage, means that
+the variable should not be automatically initialized by the compiler when
+the option @code{-ftrivial-auto-var-init} presents.
+
+With the option @code{-ftrivial-auto-var-init}, all the automatic variables
+that do not have explicit initializers will be initialized by the compiler.
+These additional compiler initializations might incur run-time overhead,
+sometimes dramatically.  This attribute can be used to mark some variables
+to be excluded from such automatical initialization in order to reduce runtime
+overhead.
+
+This attribute has no effect when the option @code{-ftrivial-auto-var-init}
+does not present.
+
 @item vector_size (@var{bytes})
 @cindex @code{vector_size} variable attribute
 This attribute specifies the vector size for the type of the declared
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 32697e6117c0..092e4a91774f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -573,9 +573,9 @@ Objective-C and Objective-C++ Dialects}.
 -ftree-parallelize-loops=@var{n}  -ftree-pre  -ftree-partial-pre  -ftree-pta @gol
 -ftree-reassoc  -ftree-scev-cprop  -ftree-sink  -ftree-slsr  -ftree-sra @gol
 -ftree-switch-conversion  -ftree-tail-merge @gol
--ftree-ter  -ftree-vectorize  -ftree-vrp  -funconstrained-commons @gol
--funit-at-a-time  -funroll-all-loops  -funroll-loops @gol
--funsafe-math-optimizations  -funswitch-loops @gol
+-ftree-ter  -ftree-vectorize  -ftree-vrp  -ftrivial-auto-var-init @gol
+-funconstrained-commons -funit-at-a-time  -funroll-all-loops @gol
+-funroll-loops -funsafe-math-optimizations  -funswitch-loops @gol
 -fipa-ra  -fvariable-expansion-in-unroller  -fvect-cost-model  -fvpt @gol
 -fweb  -fwhole-program  -fwpa  -fuse-linker-plugin -fzero-call-used-regs @gol
 --param @var{name}=@var{value}
@@ -11818,6 +11818,41 @@ Perform basic block vectorization on trees. This flag is enabled by default at
 @option{-O3} and by @option{-ftree-vectorize}, @option{-fprofile-use},
 and @option{-fauto-profile}.
 
+@item -ftrivial-auto-var-init=@var{choice}
+@opindex ftrivial-auto-var-init
+Initialize automatic variables with either a pattern or with zeroes to increase
+the security and predictability of a program by preventing uninitialized memory
+disclosure and use.
+GCC still considers an automatic variable that doesn't have an explicit
+initializer as uninitialized, -Wuninitialized will still report warning messages
+on such automatic variables.
+With this option, GCC will also initialize any padding of automatic variables
+that have structure or union types to zeroes.
+
+The three values of @var{choice} are:
+
+@itemize @bullet
+@item
+@samp{uninitialized} doesn't initialize any automatic variables.
+This is C and C++'s default.
+
+@item
+@samp{pattern} Initialize automatic variables with values which will likely
+transform logic bugs into crashes down the line, are easily recognized in a
+crash dump and without being values that programmers can rely on for useful
+program semantics.
+The current value is byte-repeatable pattern with byte "0xFE".
+The values used for pattern initialization might be changed in the future.
+
+@item
+@samp{zero} Initialize automatic variables with zeroes.
+@end itemize
+
+The default is @samp{uninitialized}.
+
+You can control this behavior for a specific variable by using the variable
+attribute @code{uninitialized} (@pxref{Variable Attributes}).
+
 @item -fvect-cost-model=@var{model}
 @opindex fvect-cost-model
 Alter the cost model used for vectorization.  The @var{model} argument
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index e43d1de490df..6fb0aefbfc7b 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -276,6 +276,13 @@ enum vect_cost_model {
   VECT_COST_MODEL_DEFAULT = 1
 };
 
+/* Automatic variable initialization type.  */
+enum auto_init_type {
+  AUTO_INIT_UNINITIALIZED = 0,
+  AUTO_INIT_PATTERN = 1,
+  AUTO_INIT_ZERO = 2
+};
+
 /* Different instrumentation modes.  */
 enum sanitize_code {
   /* AddressSanitizer.  */
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index a3afe871f6b4..5458ee8ce54f 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -4517,12 +4517,14 @@ clear_padding_add_padding (clear_padding_struct *buf,
     }
 }
 
-static void clear_padding_type (clear_padding_struct *, tree, HOST_WIDE_INT);
+static void clear_padding_type (clear_padding_struct *, tree,
+				HOST_WIDE_INT, bool);
 
 /* Clear padding bits of union type TYPE.  */
 
 static void
-clear_padding_union (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
+clear_padding_union (clear_padding_struct *buf, tree type,
+		     HOST_WIDE_INT sz, bool for_auto_init)
 {
   clear_padding_struct *union_buf;
   HOST_WIDE_INT start_off = 0, next_off = 0;
@@ -4567,7 +4569,7 @@ clear_padding_union (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
 	      continue;
 	    gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
 			&& !COMPLETE_TYPE_P (TREE_TYPE (field)));
-	    if (!buf->clear_in_mask)
+	    if (!buf->clear_in_mask && !for_auto_init)
 	      error_at (buf->loc, "flexible array member %qD does not have "
 				  "well defined padding bits for %qs",
 			field, "__builtin_clear_padding");
@@ -4578,7 +4580,7 @@ clear_padding_union (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
 	union_buf->off = start_off;
 	union_buf->size = start_size;
 	memset (union_buf->buf, ~0, start_size);
-	clear_padding_type (union_buf, TREE_TYPE (field), fldsz);
+	clear_padding_type (union_buf, TREE_TYPE (field), fldsz, for_auto_init);
 	clear_padding_add_padding (union_buf, sz - fldsz);
 	clear_padding_flush (union_buf, true);
       }
@@ -4648,7 +4650,8 @@ clear_padding_type_may_have_padding_p (tree type)
      __builtin_clear_padding (buf.base);  */
 
 static void
-clear_padding_emit_loop (clear_padding_struct *buf, tree type, tree end)
+clear_padding_emit_loop (clear_padding_struct *buf, tree type,
+			 tree end, bool for_auto_init)
 {
   tree l1 = create_artificial_label (buf->loc);
   tree l2 = create_artificial_label (buf->loc);
@@ -4659,7 +4662,7 @@ clear_padding_emit_loop (clear_padding_struct *buf, tree type, tree end)
   g = gimple_build_label (l1);
   gimple_set_location (g, buf->loc);
   gsi_insert_before (buf->gsi, g, GSI_SAME_STMT);
-  clear_padding_type (buf, type, buf->sz);
+  clear_padding_type (buf, type, buf->sz, for_auto_init);
   clear_padding_flush (buf, true);
   g = gimple_build_assign (buf->base, POINTER_PLUS_EXPR, buf->base,
 			   size_int (buf->sz));
@@ -4677,10 +4680,13 @@ clear_padding_emit_loop (clear_padding_struct *buf, tree type, tree end)
 }
 
 /* Clear padding bits for TYPE.  Called recursively from
-   gimple_fold_builtin_clear_padding.  */
+   gimple_fold_builtin_clear_padding. If FOR_AUTO_INIT,
+   not emit some of the error messages since doing that
+   might confuse the end user.  */
 
 static void
-clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
+clear_padding_type (clear_padding_struct *buf, tree type,
+		    HOST_WIDE_INT sz, bool for_auto_init)
 {
   switch (TREE_CODE (type))
     {
@@ -4762,7 +4768,7 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
 		  continue;
 		gcc_assert (TREE_CODE (ftype) == ARRAY_TYPE
 			    && !COMPLETE_TYPE_P (ftype));
-		if (!buf->clear_in_mask)
+		if (!buf->clear_in_mask && !for_auto_init)
 		  error_at (buf->loc, "flexible array member %qD does not "
 				      "have well defined padding bits for %qs",
 			    field, "__builtin_clear_padding");
@@ -4776,7 +4782,8 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
 		gcc_assert (pos >= 0 && fldsz >= 0 && pos >= cur_pos);
 		clear_padding_add_padding (buf, pos - cur_pos);
 		cur_pos = pos;
-		clear_padding_type (buf, TREE_TYPE (field), fldsz);
+		clear_padding_type (buf, TREE_TYPE (field),
+				    fldsz, for_auto_init);
 		cur_pos += fldsz;
 	      }
 	  }
@@ -4816,7 +4823,7 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
 	  buf->align = TYPE_ALIGN (elttype);
 	  buf->off = 0;
 	  buf->size = 0;
-	  clear_padding_emit_loop (buf, elttype, end);
+	  clear_padding_emit_loop (buf, elttype, end, for_auto_init);
 	  buf->base = base;
 	  buf->sz = prev_sz;
 	  buf->align = prev_align;
@@ -4826,10 +4833,10 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
 	  break;
 	}
       for (HOST_WIDE_INT i = 0; i < nelts; i++)
-	clear_padding_type (buf, TREE_TYPE (type), fldsz);
+	clear_padding_type (buf, TREE_TYPE (type), fldsz, for_auto_init);
       break;
     case UNION_TYPE:
-      clear_padding_union (buf, type, sz);
+      clear_padding_union (buf, type, sz, for_auto_init);
       break;
     case REAL_TYPE:
       gcc_assert ((size_t) sz <= clear_padding_unit);
@@ -4853,14 +4860,14 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
       break;
     case COMPLEX_TYPE:
       fldsz = int_size_in_bytes (TREE_TYPE (type));
-      clear_padding_type (buf, TREE_TYPE (type), fldsz);
-      clear_padding_type (buf, TREE_TYPE (type), fldsz);
+      clear_padding_type (buf, TREE_TYPE (type), fldsz, for_auto_init);
+      clear_padding_type (buf, TREE_TYPE (type), fldsz, for_auto_init);
       break;
     case VECTOR_TYPE:
       nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
       fldsz = int_size_in_bytes (TREE_TYPE (type));
       for (HOST_WIDE_INT i = 0; i < nelts; i++)
-	clear_padding_type (buf, TREE_TYPE (type), fldsz);
+	clear_padding_type (buf, TREE_TYPE (type), fldsz, for_auto_init);
       break;
     case NULLPTR_TYPE:
       gcc_assert ((size_t) sz <= clear_padding_unit);
@@ -4896,7 +4903,7 @@ clear_type_padding_in_mask (tree type, unsigned char *mask)
   buf.sz = int_size_in_bytes (type);
   buf.size = 0;
   buf.union_ptr = mask;
-  clear_padding_type (&buf, type, buf.sz);
+  clear_padding_type (&buf, type, buf.sz, false);
   clear_padding_flush (&buf, true);
 }
 
@@ -4906,9 +4913,10 @@ static bool
 gimple_fold_builtin_clear_padding (gimple_stmt_iterator *gsi)
 {
   gimple *stmt = gsi_stmt (*gsi);
-  gcc_assert (gimple_call_num_args (stmt) == 2);
+  gcc_assert (gimple_call_num_args (stmt) == 3);
   tree ptr = gimple_call_arg (stmt, 0);
   tree typearg = gimple_call_arg (stmt, 1);
+  bool for_auto_init = (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 2));
   tree type = TREE_TYPE (TREE_TYPE (typearg));
   location_t loc = gimple_location (stmt);
   clear_padding_struct buf;
@@ -4965,7 +4973,7 @@ gimple_fold_builtin_clear_padding (gimple_stmt_iterator *gsi)
 	  buf.sz = eltsz;
 	  buf.align = TYPE_ALIGN (elttype);
 	  buf.alias_type = build_pointer_type (elttype);
-	  clear_padding_emit_loop (&buf, elttype, end);
+	  clear_padding_emit_loop (&buf, elttype, end, for_auto_init);
 	}
     }
   else
@@ -4978,7 +4986,7 @@ gimple_fold_builtin_clear_padding (gimple_stmt_iterator *gsi)
 	  gsi_insert_before (gsi, g, GSI_SAME_STMT);
 	}
       buf.alias_type = build_pointer_type (type);
-      clear_padding_type (&buf, type, buf.sz);
+      clear_padding_type (&buf, type, buf.sz, for_auto_init);
       clear_padding_flush (&buf, true);
     }
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 93a2121fea18..cee8649cf3a7 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -249,6 +249,11 @@ static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
 static hash_map<tree, tree> *oacc_declare_returns;
 static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
 					   bool (*) (tree), fallback_t, bool);
+static void gimple_add_init_for_auto_var (tree, enum auto_init_type, bool,
+					  gimple_seq *);
+static void maybe_with_size_expr (tree *);
+static void prepare_gimple_addressable (tree *, gimple_seq *);
+
 
 /* Shorter alias name for the above function for use in gimplify.c
    only.  */
@@ -1743,6 +1748,114 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
   return NULL_TREE;
 }
 
+
+/* Build a call to internal const function DEFERRED_INIT:
+   1st argument: SIZE of the DECL;
+   2nd argument: INIT_TYPE;
+   3rd argument: IS_VLA, 0 NO, 1 YES;
+
+   as DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, IS_VLA).  */
+
+static gimple *
+build_deferred_init (tree decl,
+		     enum auto_init_type init_type,
+		     bool is_vla)
+{
+  gcc_assert ((is_vla && TREE_CODE (decl) == WITH_SIZE_EXPR)
+	      || (!is_vla && TREE_CODE (decl) != WITH_SIZE_EXPR));
+
+  tree decl_size = NULL_TREE;
+  tree init_type_node
+    = build_int_cst (integer_type_node, (int) init_type);
+  tree is_vla_node
+    = build_int_cst (integer_type_node, (int) is_vla);
+
+   if (TREE_CODE (decl) == WITH_SIZE_EXPR)
+     decl_size = TREE_OPERAND (decl, 1);
+   else
+     decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
+
+   return gimple_build_call_internal (IFN_DEFERRED_INIT, 3,
+				      decl_size, init_type_node, is_vla_node);
+}
+
+/* Generate initialization to automatic variable DECL based on INIT_TYPE.  */
+static void
+gimple_add_init_for_auto_var (tree decl,
+			      enum auto_init_type init_type,
+			      bool is_vla,
+			      gimple_seq *seq_p)
+{
+  gcc_assert (VAR_P (decl) && !DECL_EXTERNAL (decl) && !TREE_STATIC (decl));
+  gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
+
+  /* If this DECL is a variable sized type, we must remember the size.  */
+  tree orig_decl = decl;
+  maybe_with_size_expr (&decl);
+
+  gimple *call = build_deferred_init (decl, init_type, is_vla);
+  gimple_call_set_lhs (call, orig_decl);
+  gimplify_seq_add_stmt (seq_p, call);
+}
+
+/* Generate padding initialization for automatic vairable DECL.
+   C guarantees that brace-init with fewer initializers than members
+   aggregate will initialize the rest of the aggregate as-if it were
+   static initialization.  In turn static initialization guarantees
+   that padding is initialized to zero. So, we always initialize paddings
+   to zeroes regardless INIT_TYPE.
+   To do the padding initialization, we insert a call to
+   __BUILTIN_CLEAR_PADDING (&decl, 0, for_auto_init = true).
+   */
+static void
+gimple_add_padding_init_for_auto_var (tree decl, bool is_vla,
+				      gimple_seq *seq_p)
+{
+  tree addr_of_decl = NULL_TREE;
+  bool for_auto_init = true;
+  tree fn = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
+
+  if (is_vla)
+    {
+      /* The temporary address variable for this vla should be
+	 created in gimplify_vla_decl.  */
+      gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
+      gcc_assert (TREE_CODE (DECL_VALUE_EXPR (decl)) == INDIRECT_REF);
+      addr_of_decl = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0);
+    }
+  else
+    {
+      prepare_gimple_addressable (&decl, seq_p);
+      mark_addressable (decl);
+      addr_of_decl = build_fold_addr_expr (decl);
+    }
+
+
+  /* for languages that do not support BUILT_IN_CLEAR_PADDING, create the
+     function node for padding initialization.  */
+  if (!fn)
+    {
+      tree ftype = build_function_type_list (void_type_node,
+					     ptr_type_node,
+					     ptr_type_node,
+					     integer_type_node,
+					     NULL_TREE);
+      fn = add_builtin_function ("__builtin_clear_padding", ftype,
+				 BUILT_IN_CLEAR_PADDING, BUILT_IN_NORMAL,
+				 NULL, NULL_TREE);
+      set_call_expr_flags (fn, ECF_NOTHROW | ECF_LEAF);
+      set_builtin_decl (BUILT_IN_CLEAR_PADDING, fn, false);
+    }
+
+  gimple *call = gimple_build_call (fn,
+				    3, addr_of_decl,
+				    build_zero_cst (TREE_TYPE (addr_of_decl)),
+				    build_int_cst (integer_type_node,
+						   (int) for_auto_init));
+  gimplify_seq_add_stmt (seq_p, call);
+}
+
+
 /* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
    and initialization explicit.  */
 
@@ -1839,6 +1952,31 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
 	       as they may contain a label address.  */
 	    walk_tree (&init, force_labels_r, NULL, NULL);
 	}
+      /* When there is no explicit initializer, if the user requested,
+	 We should insert an artifical initializer for this automatic
+	 variable.  */
+      else if (opt_for_fn (current_function_decl, flag_auto_var_init)
+		 > AUTO_INIT_UNINITIALIZED
+	       && !lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl))
+	       && !TREE_STATIC (decl))
+	{
+	  gimple_add_init_for_auto_var (decl,
+					opt_for_fn (current_function_decl,
+						    flag_auto_var_init),
+					is_vla,
+					seq_p);
+	  /* The expanding of a call to the above .DEFERRED_INIT will apply
+	     block initialization to the whole space covered by this variable.
+	     As a result, all the paddings will be initialized to zeroes
+	     for zero initialization and 0xFE byte-repeatable patterns for
+	     pattern initialization.
+	     In order to make the paddings as zeroes for pattern init, We
+	     should add a call to __builtin_clear_padding to clear the
+	     paddings to zero in compatiple with CLANG.  */
+	  if (opt_for_fn (current_function_decl, flag_auto_var_init)
+	      == AUTO_INIT_PATTERN)
+	    gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p);
+	}
     }
 
   return GS_ALL_DONE;
@@ -3410,11 +3548,15 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
 	  {
 	    /* Remember the original type of the argument in an internal
 	       dummy second argument, as in GIMPLE pointer conversions are
-	       useless.  */
+	       useless. also mark this call as not for automatic initialization
+	       in the internal dummy third argument.  */
 	    p = CALL_EXPR_ARG (*expr_p, 0);
+	    bool for_auto_init = false;
 	    *expr_p
-	      = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p,
-				     build_zero_cst (TREE_TYPE (p)));
+	      = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 3, p,
+				     build_zero_cst (TREE_TYPE (p)),
+				     build_int_cst (integer_type_node,
+						    (int) for_auto_init));
 	    return GS_OK;
 	  }
 	break;
@@ -5280,6 +5422,7 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
 {
   enum gimplify_status ret = GS_UNHANDLED;
   bool changed;
+  tree object = NULL_TREE;
 
   do
     {
@@ -5394,6 +5537,19 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
 	     crack at this before we break it down.  */
 	  if (ret != GS_UNHANDLED)
 	    break;
+	  /* If the user requests to initialize automatic variables, we
+	     should initialize paddings inside the variable. Add a call to
+	     __BUILTIN_CLEAR_PADDING (&object, 0, for_auto_init = true) to
+	     initialize paddings of object always to zero regardless of
+	     INIT_TYPE.  */
+	  object = TREE_OPERAND (*expr_p, 0);
+	  if (opt_for_fn (current_function_decl, flag_auto_var_init)
+		> AUTO_INIT_UNINITIALIZED
+	      && VAR_P (object)
+	      && !DECL_EXTERNAL (object)
+	      && !TREE_STATIC (object))
+	    gimple_add_padding_init_for_auto_var (object, false, pre_p);
+
 	  /* If we're initializing from a CONSTRUCTOR, break this into
 	     individual MODIFY_EXPRs.  */
 	  return gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 1360a00f0b93..620a2f9fee2a 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2977,6 +2977,114 @@ expand_UNIQUE (internal_fn, gcall *stmt)
     emit_insn (pattern);
 }
 
+/* Expand the IFN_DEFERRED_INIT function:
+   Initialize the LHS variable with zero/pattern according to its second
+   argument INIT_TYPE.
+   if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
+   if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
+     to initialize;
+   all the memory covered by this LHS variable is initialized including
+   paddings.
+   The reasons to choose 0xFE for pattern initialization are:
+     1. It is a non-canonical virtual address on x86_64, and at the
+	high end of the i386 kernel address space.
+     2. It is a very large float value (-1.694739530317379e+38).
+     3. It is also an unusual number for integers.  */
+#define INIT_PATTERN_VALUE  0xFE
+static void
+expand_DEFERRED_INIT (internal_fn, gcall *stmt)
+{
+  tree var = gimple_call_lhs (stmt);
+  tree size_of_var = gimple_call_arg (stmt, 0);
+  tree vlaaddr = NULL_TREE;
+  tree var_type = TREE_TYPE (var);
+  bool is_vla = (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 2));
+  enum auto_init_type init_type
+    = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
+
+  gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
+
+  /* if this variable is a VLA, get its SIZE and ADDR first.  */
+  if (is_vla)
+    {
+      /* The temporary address variable for this vla should have been
+	 created during gimplification phase.  Refer to gimplify_vla_decl
+	 for details.  */
+      tree var_decl = (TREE_CODE (var) == SSA_NAME) ?
+		       SSA_NAME_VAR (var) : var;
+      gcc_assert (DECL_HAS_VALUE_EXPR_P (var_decl));
+      gcc_assert (TREE_CODE (DECL_VALUE_EXPR (var_decl)) == INDIRECT_REF);
+      /* Get the address of this vla variable.  */
+      vlaaddr = TREE_OPERAND (DECL_VALUE_EXPR (var_decl), 0);
+    }
+
+  if (is_vla || (!use_register_for_decl (var)))
+    {
+    /* If this is a VLA or the variable is not in register,
+       expand to a memset to initialize it.  */
+      if (TREE_CODE (var) == SSA_NAME)
+	var = SSA_NAME_VAR (var);
+      tree addr = is_vla ? vlaaddr: build_fold_addr_expr (var);
+      tree value = (init_type == AUTO_INIT_PATTERN) ?
+		    build_int_cst (unsigned_char_type_node,
+				   INIT_PATTERN_VALUE) :
+		    build_zero_cst (unsigned_char_type_node);
+      tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
+				     3, addr, value, size_of_var);
+      /* Expand this memset call.  */
+      expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
+    }
+  else
+    {
+    /* If this variable is in a register, use expand_assignment might
+       generate better code.  */
+      tree pattern = NULL_TREE;
+      unsigned HOST_WIDE_INT total_bytes
+	= tree_to_uhwi (TYPE_SIZE_UNIT (var_type));
+
+      if (INTEGRAL_TYPE_P (var_type) || POINTER_TYPE_P (var_type))
+	{
+	  unsigned char *ptr = (unsigned char *)xmalloc (total_bytes);
+	  for (unsigned int i = 0; i < total_bytes; i++)
+	    ptr[i] = INIT_PATTERN_VALUE;
+	  wide_int result = wi::from_buffer (ptr, total_bytes);
+	  pattern =  wide_int_to_tree (var_type, result);
+	}
+      else if (SCALAR_FLOAT_TYPE_P (var_type))
+	{
+	  unsigned int max_index = 2 + 2 * total_bytes;
+	  char *ptr= (char *)xmalloc (max_index);
+	  ptr[0] = '0';
+	  ptr[1] = 'x';
+	  for (unsigned int i = 2; i < max_index; i += 2)
+	    ptr[i] = 'F';
+	  for (unsigned int i = 3; i < max_index; i += 2)
+	    ptr[i] = 'E';
+	  REAL_VALUE_TYPE r_var;
+	  real_from_string (&r_var, ptr);
+	  pattern = build_real (var_type, r_var);
+	}
+      else
+	{
+	  tree index_type = build_index_type (size_int (total_bytes - 1));
+	  tree array_type = build_array_type (unsigned_char_type_node,
+					      index_type);
+	  tree element = build_int_cst (unsigned_char_type_node,
+					INIT_PATTERN_VALUE);
+	  vec<constructor_elt, va_gc> *elts = NULL;
+	  for (unsigned int i = 0; i < total_bytes; i++)
+	    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, element);
+	  pattern = build_constructor (array_type, elts);
+	  pattern = build1 (VIEW_CONVERT_EXPR, var_type, pattern);
+	}
+
+      tree init = (init_type == AUTO_INIT_PATTERN) ?
+		   pattern :
+		   build_zero_cst (TREE_TYPE (var));
+      expand_assignment (var, init, false);
+    }
+}
+
 /* The size of an OpenACC compute dimension.  */
 
 static void
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 3ac9ae68b2a6..dc84b7b7ca79 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -360,6 +360,11 @@ DEF_INTERNAL_FN (VEC_CONVERT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (PHI, 0, NULL)
 
+/* A function to represent an artifical initialization to an uninitialized
+   automatic variable.  The first argument is the variable itself, the
+   second argument is the initialization type.  */
+DEF_INTERNAL_FN (DEFERRED_INIT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+
 /* DIM_SIZE and DIM_POS return the size of a particular compute
    dimension and the executing thread's position within that
    dimension.  DIM_POS is pure (and not const) so that it isn't
diff --git a/gcc/testsuite/c-c++-common/auto-init-1.c b/gcc/testsuite/c-c++-common/auto-init-1.c
new file mode 100644
index 000000000000..8b8ba3dd7e8d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-1.c
@@ -0,0 +1,39 @@
+/* Verify zero initialization for integer and pointer type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+  N1 = 0,
+  N2,
+  N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+  char temp1;
+  short temp2;
+  int temp3;
+  enum E temp4;
+  long temp5;
+  long long temp6;
+  int *temp7;
+  bool temp8;
+
+  bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+  return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(1, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(2, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(1, 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-10.c b/gcc/testsuite/c-c++-common/auto-init-10.c
new file mode 100644
index 000000000000..0a8841e6e0f9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-10.c
@@ -0,0 +1,17 @@
+/* Verify the variable attribute "uninitialized".  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+extern void bar (char, long long *) __attribute__ ((uninitialized)); /* { dg-warning "'uninitialized' attribute ignored" } */
+
+void foo()
+{
+  short temp1;
+  long long __attribute__ ((uninitialized)) temp2[10];
+
+  bar (temp1, temp2);
+  return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(2, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "temp2 = .DEFERRED_INIT \\(" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-11.c b/gcc/testsuite/c-c++-common/auto-init-11.c
new file mode 100644
index 000000000000..a2d66908d83e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-11.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+  int arr[n];
+  bar (arr[2]);
+  return;
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 2, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-12.c b/gcc/testsuite/c-c++-common/auto-init-12.c
new file mode 100644
index 000000000000..f05d743fda02
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-12.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+  int arr[n];
+  bar (arr[2]);
+  return;
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 1, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-13.c b/gcc/testsuite/c-c++-common/auto-init-13.c
new file mode 100644
index 000000000000..b0c0365b288a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-13.c
@@ -0,0 +1,23 @@
+/* Verify the auto initialization of structure or union with a flexible array
+   member.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+struct a {
+  int b;
+  int array[];
+};
+union tar {
+  struct a bar;
+  char buf;
+};
+
+int foo()
+{
+  struct a d;
+  union tar var;
+  return d.b + var.bar.b;
+}
+
+/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-14.c b/gcc/testsuite/c-c++-common/auto-init-14.c
new file mode 100644
index 000000000000..986bb19faaf0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-14.c
@@ -0,0 +1,23 @@
+/* Verify the auto initialization of structure or union with a flexible array
+   member.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+struct a {
+  int b;
+  int array[];
+};
+union tar {
+  struct a bar;
+  char buf;
+};
+
+int foo()
+{
+  struct a d;
+  union tar var;
+  return d.b + var.bar.b;
+}
+
+/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-15.c b/gcc/testsuite/c-c++-common/auto-init-15.c
new file mode 100644
index 000000000000..aa9d7fab68a6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-15.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+void g(void *);
+
+void foo(int a)
+{
+  int x[a][a];
+  g(x);
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 2, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-16.c b/gcc/testsuite/c-c++-common/auto-init-16.c
new file mode 100644
index 000000000000..86493eef9e47
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-16.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+void g(void *);
+
+void foo(int a)
+{
+  int x[a][a];
+  g(x);
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 1, 1\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-2.c b/gcc/testsuite/c-c++-common/auto-init-2.c
new file mode 100644
index 000000000000..71955b54ba03
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-2.c
@@ -0,0 +1,39 @@
+/* Verify pattern initialization for integer and pointer type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+  N1 = 0,
+  N2,
+  N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+  char temp1;
+  short temp2;
+  int temp3;
+  enum E temp4;
+  long temp5;
+  long long temp6;
+  int *temp7;
+  bool temp8;
+
+  bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+  return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(1, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(2, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(1, 1, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-3.c b/gcc/testsuite/c-c++-common/auto-init-3.c
new file mode 100644
index 000000000000..312275666381
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-3.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for floating point type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+long double result;
+
+long double foo()
+{
+  float temp1;
+  double temp2;
+  long double temp3;
+  
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(4, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(16, 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-4.c b/gcc/testsuite/c-c++-common/auto-init-4.c
new file mode 100644
index 000000000000..15a431726dcd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-4.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for floating point type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+long double result;
+
+long double foo()
+{
+  float temp1;
+  double temp2;
+  long double temp3;
+  
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(4, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(16, 1, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-5.c b/gcc/testsuite/c-c++-common/auto-init-5.c
new file mode 100644
index 000000000000..54f90bc890b5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-5.c
@@ -0,0 +1,21 @@
+/* Verify zero initialization for complex type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+  _Complex float temp1;
+  _Complex double temp2;
+  _Complex long double temp3;
+
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(16, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(32, 2, 0\\)" "gimple" } } */
+
diff --git a/gcc/testsuite/c-c++-common/auto-init-6.c b/gcc/testsuite/c-c++-common/auto-init-6.c
new file mode 100644
index 000000000000..4124a2b183aa
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-6.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for complex type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+  _Complex float temp1;
+  _Complex double temp2;
+  _Complex long double temp3;
+
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(16, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(32, 1, 0\\)" "gimple" } } */
+
diff --git a/gcc/testsuite/c-c++-common/auto-init-7.c b/gcc/testsuite/c-c++-common/auto-init-7.c
new file mode 100644
index 000000000000..19986969a8f7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-7.c
@@ -0,0 +1,35 @@
+/* Verify zero initialization for array, union, and structure type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+struct S
+{
+  int f1;
+  float f2;
+  char f3[20];
+};
+
+union U
+{
+  char u1[5];
+  int u2;
+  float u3; 
+};
+
+double result;
+
+double foo()
+{
+  int temp1[3];
+  double temp2[3];
+  struct S temp3;
+  union U temp4;
+  
+  result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+  return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(12, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(24, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(28, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-8.c b/gcc/testsuite/c-c++-common/auto-init-8.c
new file mode 100644
index 000000000000..9778e911e3ad
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-8.c
@@ -0,0 +1,35 @@
+/* Verify pattern initialization for array, union, and structure type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+struct S
+{
+  int f1;
+  float f2;
+  char f3[20];
+};
+
+union U
+{
+  char u1[5];
+  int u2;
+  float u3; 
+};
+
+double result;
+
+double foo()
+{
+  int temp1[3];
+  double temp2[3];
+  struct S temp3;
+  union U temp4;
+  
+  result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+  return result;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(12, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(24, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(28, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(8, 1, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-9.c b/gcc/testsuite/c-c++-common/auto-init-9.c
new file mode 100644
index 000000000000..90bbd8cb1afe
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-9.c
@@ -0,0 +1,17 @@
+/* Verify the variable attribute "uninitialized".  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-tree-gimple" } */
+
+extern void bar (char, long long *) __attribute__ ((uninitialized)); /* { dg-warning "'uninitialized' attribute ignored" } */
+
+void foo()
+{
+  short temp1;
+  long long __attribute__ ((uninitialized)) temp2[10];
+
+  bar (temp1, temp2);
+  return;
+}
+
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(2, 2, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "temp2 = .DEFERRED_INIT \\(8, 2, 0\\)" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-esra.c b/gcc/testsuite/c-c++-common/auto-init-esra.c
new file mode 100644
index 000000000000..77ec02355df4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-esra.c
@@ -0,0 +1,35 @@
+/* Verify the strength reduction adjustment for -ftrivial-auto-var-init.  */ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftrivial-auto-var-init=zero -fdump-tree-gimple -fdump-tree-esra" } */
+
+
+typedef double VECTOR[3];
+
+enum
+{
+ X = 0,
+ Y = 1,
+ Z = 2,
+ T = 3
+};
+
+void Assign_Vector(VECTOR d, VECTOR s)
+{
+ d[X] = s[X];
+ d[Y] = s[Y];
+ d[Z] = s[Z];
+}
+
+void VCross(VECTOR a, const VECTOR b, const VECTOR c)
+{
+ VECTOR tmp;
+
+ tmp[X] = b[Y] * c[Z] - b[Z] * c[Y];
+ tmp[Y] = b[Z] * c[X] - b[X] * c[Z];
+ tmp[Z] = b[X] * c[Y] - b[Y] * c[X];
+
+ Assign_Vector(a, tmp);
+}
+
+/* { dg-final { scan-tree-dump-times "tmp = .DEFERRED_INIT \\(24, 2, 0\\)" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times ".DEFERRED_INIT \\(8, 2, 0\\)" 3 "esra" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-padding-1.c b/gcc/testsuite/c-c++-common/auto-init-padding-1.c
new file mode 100644
index 000000000000..97f78ee7d56a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-padding-1.c
@@ -0,0 +1,23 @@
+/* Verify the padding initialization for pattern initialization, we always emit
+ * a call to __builtin_clear_padding to initialize the paddings to zero.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-tree-gimple" } */
+
+
+struct test_small_hole {
+  int one;
+  char two;
+  /* 3 byte padding hole here. */
+  int three;
+  unsigned long four;
+};
+
+extern void g (struct test_small_hole);
+void foo(int a)
+{
+  struct test_small_hole s; 
+  g(s);
+}
+
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(24, 1, 0\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump "__builtin_clear_padding" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-padding-2.c b/gcc/testsuite/c-c++-common/auto-init-padding-2.c
new file mode 100644
index 000000000000..e2b50dc5ae8e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-padding-2.c
@@ -0,0 +1,114 @@
+/* To test that the compiler can fill all the paddings to zeroes for the 
+   structures when the auto variable is partially initialized,  fully 
+   initialized, or not initialized for -ftrivial-auto-var-init=zero.  */
+/* { dg-do run} */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+/* Structure with no padding. */
+struct test_packed {
+  unsigned long one;
+  unsigned long two;
+  unsigned long three;
+  unsigned long four;
+} p1;
+
+/* Simple structure with padding likely to be covered by compiler. */
+struct test_small_hole {
+  unsigned long one;
+  char two;
+  /* 3 byte padding hole here. */
+  int three;
+  unsigned long four;
+} sh1;
+
+/* Try to trigger unhandled padding in a structure. */
+struct test_aligned {
+  unsigned int internal1;
+  unsigned long long internal2;
+} __attribute__((__aligned__(64)));
+
+struct test_aligned a1;
+
+struct test_big_hole {
+  unsigned char one;
+  unsigned char two;
+  unsigned char three;
+  /* 61 byte padding hole here. */
+  struct test_aligned four;
+} __attribute__((__aligned__(64))); 
+
+struct test_big_hole bh1;
+
+struct test_trailing_hole {
+  char *one;
+  char *two;
+  char *three;
+  char four;
+  /* "sizeof(unsigned long) - 1" byte padding hole here. */
+} th1;
+
+__attribute__((noipa)) void
+foo (struct test_packed *p, struct test_small_hole *sh, struct test_aligned *a,
+     struct test_big_hole *bh, struct test_trailing_hole *th)
+{
+  p->one = 1; p->two = 2; p->three = 3; p->four = 4;
+  sh->one = 11; sh->two = 12; sh->three = 13; sh->four = 14;
+  a->internal1 = 21; a->internal2 = 22;
+  bh->one = 31; bh->two = 32; bh->three = 33;
+  bh->four.internal1 = 34; bh->four.internal2 = 35; 
+  th->one = 0; th->two = 0; th->three = 0; th->four = 44;
+}
+
+int main ()
+{
+  struct test_packed p2;
+  struct test_small_hole sh2;
+  struct test_aligned a2;
+  struct test_big_hole bh2;
+  struct test_trailing_hole th2;
+
+  struct test_packed p3 = {.one = 1};
+  struct test_small_hole sh3 = {.two = 12};
+  struct test_aligned a3 = {.internal1 = 21};
+  struct test_big_hole bh3 = {.one = 31};
+  struct test_trailing_hole th3 = {.three = 0};
+
+  struct test_packed p4 = {.one = 1, .two = 2, .three = 3, .four = 4};
+  struct test_small_hole sh4 = {.one = 11, .two = 12, .three = 13, .four = 14};
+  struct test_aligned a4 = {.internal1 = 21, .internal2 = 22};
+  struct test_big_hole bh4 = {.one = 31, .two = 32, .three = 33};
+  struct test_trailing_hole th4 = {.one = 0, .two = 0, .three = 0, .four = 44};
+
+  foo (&p1, &sh1, &a1, &bh1, &th1);
+  foo (&p2, &sh2, &a2, &bh2, &th2);
+  foo (&p3, &sh3, &a3, &bh3, &th3);
+  bh4.four.internal1 = 34; bh4.four.internal2 = 35;
+
+  __builtin_clear_padding (&p1);
+  __builtin_clear_padding (&sh1);
+  __builtin_clear_padding (&a1);
+  __builtin_clear_padding (&bh1);
+  __builtin_clear_padding (&th1);
+
+  if (__builtin_memcmp (&p1, &p2, sizeof (p1))
+      || __builtin_memcmp (&sh1, &sh2, sizeof (sh1))
+      || __builtin_memcmp (&a1, &a2, sizeof (a1))
+      || __builtin_memcmp (&bh1, &bh2, sizeof (bh1))
+      || __builtin_memcmp (&th1, &th2, sizeof (th1)))
+    __builtin_abort ();
+  if (__builtin_memcmp (&p1, &p3, sizeof (p1))
+      || __builtin_memcmp (&sh1, &sh3, sizeof (sh1))
+      || __builtin_memcmp (&a1, &a3, sizeof (a1))
+      || __builtin_memcmp (&bh1, &bh3, sizeof (bh1))
+      || __builtin_memcmp (&th1, &th3, sizeof (th1)))
+    __builtin_abort ();
+  if (__builtin_memcmp (&p1, &p4, sizeof (p1))
+      || __builtin_memcmp (&sh1, &sh4, sizeof (sh1))
+      || __builtin_memcmp (&a1, &a4, sizeof (a1))
+      || __builtin_memcmp (&bh1, &bh4, sizeof (bh1))
+      || __builtin_memcmp (&th1, &th4, sizeof (th1)))
+    __builtin_abort ();
+
+
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/auto-init-padding-3.c b/gcc/testsuite/c-c++-common/auto-init-padding-3.c
new file mode 100644
index 000000000000..e2c48c002c95
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/auto-init-padding-3.c
@@ -0,0 +1,114 @@
+/* To test that the compiler can fill all the paddings to zeroes for the 
+   structures when the auto variable is partially initialized,  fully 
+   initialized, or not initialized for -ftrivial-auto-var-init=pattern.  */
+/* { dg-do run} */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+/* Structure with no padding. */
+struct test_packed {
+  unsigned long one;
+  unsigned long two;
+  unsigned long three;
+  unsigned long four;
+} p1;
+
+/* Simple structure with padding likely to be covered by compiler. */
+struct test_small_hole {
+  unsigned long one;
+  char two;
+  /* 3 byte padding hole here. */
+  int three;
+  unsigned long four;
+} sh1;
+
+/* Try to trigger unhandled padding in a structure. */
+struct test_aligned {
+  unsigned int internal1;
+  unsigned long long internal2;
+} __attribute__((__aligned__(64)));
+
+struct test_aligned a1;
+
+struct test_big_hole {
+  unsigned char one;
+  unsigned char two;
+  unsigned char three;
+  /* 61 byte padding hole here. */
+  struct test_aligned four;
+} __attribute__((__aligned__(64))); 
+
+struct test_big_hole bh1;
+
+struct test_trailing_hole {
+  char *one;
+  char *two;
+  char *three;
+  char four;
+  /* "sizeof(unsigned long) - 1" byte padding hole here. */
+} th1;
+
+__attribute__((noipa)) void
+foo (struct test_packed *p, struct test_small_hole *sh, struct test_aligned *a,
+     struct test_big_hole *bh, struct test_trailing_hole *th)
+{
+  p->one = 1; p->two = 2; p->three = 3; p->four = 4;
+  sh->one = 11; sh->two = 12; sh->three = 13; sh->four = 14;
+  a->internal1 = 21; a->internal2 = 22;
+  bh->one = 31; bh->two = 32; bh->three = 33;
+  bh->four.internal1 = 34; bh->four.internal2 = 35; 
+  th->one = 0; th->two = 0; th->three = 0; th->four = 44;
+}
+
+int main ()
+{
+  struct test_packed p2;
+  struct test_small_hole sh2;
+  struct test_aligned a2;
+  struct test_big_hole bh2;
+  struct test_trailing_hole th2;
+
+  struct test_packed p3 = {.one = 1};
+  struct test_small_hole sh3 = {.two = 12};
+  struct test_aligned a3 = {.internal1 = 21};
+  struct test_big_hole bh3 = {.one = 31};
+  struct test_trailing_hole th3 = {.three = 0};
+
+  struct test_packed p4 = {.one = 1, .two = 2, .three = 3, .four = 4};
+  struct test_small_hole sh4 = {.one = 11, .two = 12, .three = 13, .four = 14};
+  struct test_aligned a4 = {.internal1 = 21, .internal2 = 22};
+  struct test_big_hole bh4 = {.one = 31, .two = 32, .three = 33};
+  struct test_trailing_hole th4 = {.one = 0, .two = 0, .three = 0, .four = 44};
+
+  foo (&p1, &sh1, &a1, &bh1, &th1);
+  foo (&p2, &sh2, &a2, &bh2, &th2);
+  foo (&p3, &sh3, &a3, &bh3, &th3);
+  bh4.four.internal1 = 34; bh4.four.internal2 = 35;
+
+  __builtin_clear_padding (&p1);
+  __builtin_clear_padding (&sh1);
+  __builtin_clear_padding (&a1);
+  __builtin_clear_padding (&bh1);
+  __builtin_clear_padding (&th1);
+
+  if (__builtin_memcmp (&p1, &p2, sizeof (p1))
+      || __builtin_memcmp (&sh1, &sh2, sizeof (sh1))
+      || __builtin_memcmp (&a1, &a2, sizeof (a1))
+      || __builtin_memcmp (&bh1, &bh2, sizeof (bh1))
+      || __builtin_memcmp (&th1, &th2, sizeof (th1)))
+    __builtin_abort ();
+  if (__builtin_memcmp (&p1, &p3, sizeof (p1))
+      || __builtin_memcmp (&sh1, &sh3, sizeof (sh1))
+      || __builtin_memcmp (&a1, &a3, sizeof (a1))
+      || __builtin_memcmp (&bh1, &bh3, sizeof (bh1))
+      || __builtin_memcmp (&th1, &th3, sizeof (th1)))
+    __builtin_abort ();
+  if (__builtin_memcmp (&p1, &p4, sizeof (p1))
+      || __builtin_memcmp (&sh1, &sh4, sizeof (sh1))
+      || __builtin_memcmp (&a1, &a4, sizeof (a1))
+      || __builtin_memcmp (&bh1, &bh4, sizeof (bh1))
+      || __builtin_memcmp (&th1, &th4, sizeof (th1)))
+    __builtin_abort ();
+
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C
new file mode 100644
index 000000000000..33c17441384f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_a.C
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int  get_time ();
+
+class A 
+{
+public:
+  A ();
+  ~A () {
+    if (I) delete I;
+  }
+
+private:
+  int* I;
+};
+
+bool get_url (A *);
+
+class M {
+
+ public:
+__attribute__ ((always_inline))  int GetC (int *c)  {
+
+    A details_str;
+    if (!get_url (&details_str))
+      {
+        incr ();
+        return 1;
+      }
+
+    *c = get_time ();
+    return -1;
+  }
+
+  void do_sth();
+  void do_sth2();
+   
+  void P (int64 t)
+    {
+      int cc; /* { dg-bogus "uninitialized" "uninitialized variable warning" }  */ 
+      if (GetC (&cc) >= 0 )
+        return;
+      
+      if (t && cc <= 0 )  /* { dg-bogus "uninitialized" "uninitialized variable warning" } */
+        {
+          this->do_sth();
+          return;
+        }
+
+    do_sth2();
+  }
+};
+
+M* m; 
+void foo(int x)
+{
+  m = new M;
+  m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_b.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_b.C
new file mode 100644
index 000000000000..6b6bdaed71e0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-1_b.C
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int  get_time ();
+
+class A 
+{
+public:
+  A ();
+  ~A () {
+    if (I) delete I;
+  }
+
+private:
+  int* I;
+};
+
+bool get_url (A *);
+
+class M {
+
+ public:
+__attribute__ ((always_inline))  int GetC (int *c)  {
+
+    A details_str;
+    if (!get_url (&details_str))
+      {
+        incr ();
+        return 1;
+      }
+
+    *c = get_time ();
+    return -1;
+  }
+
+  void do_sth();
+  void do_sth2();
+   
+  void P (int64 t)
+    {
+      int cc; /* { dg-message "note: 'cc' was declared here" } */
+      if (GetC (&cc) <= 0 ) /* return flag checked wrongly */
+        return;
+      
+      if (t && cc <= 0 )  /* { dg-warning "uninitialized" "uninitialized variable warning" } */
+        {
+          this->do_sth();
+          return;
+        }
+
+    do_sth2();
+  }
+};
+
+M* m; 
+void foo(int x)
+{
+  m = new M;
+  m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C
new file mode 100644
index 000000000000..fc18cb1e7c91
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_a.C
@@ -0,0 +1,62 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int  get_time ();
+
+class A 
+{
+public:
+  A ();
+  ~A () {
+    if (I) delete I;
+  }
+
+private:
+  int* I;
+};
+
+bool get_url (A *);
+
+class M {
+
+ public:
+__attribute__ ((always_inline))  bool GetC (int *c)  {
+
+    A details_str;
+    if (get_url (&details_str))
+      {
+        *c = get_time ();
+        return true;
+      }
+
+    return false;
+  }
+
+  void do_sth();
+  void do_sth2();
+   
+  void P (int64 t)
+    {
+      int cc; 
+      if (!GetC (&cc)) /* return flag checked properly */
+        return;
+      
+      if (cc <= 0)  /* { dg-bogus "uninitialized" "uninitialized variable warning" } */
+        {
+          this->do_sth();
+          return;
+        }
+
+    do_sth2();
+  }
+};
+
+M* m; 
+void foo(int x)
+{
+  m = new M;
+  m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_b.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_b.C
new file mode 100644
index 000000000000..e85a36f16fff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-2_b.C
@@ -0,0 +1,62 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int  get_time ();
+
+class A 
+{
+public:
+  A ();
+  ~A () {
+    if (I) delete I;
+  }
+
+private:
+  int* I;
+};
+
+bool get_url (A *);
+
+class M {
+
+ public:
+__attribute__ ((always_inline))  bool GetC (int *c)  {
+
+    A details_str;
+    if (get_url (&details_str))
+      {
+        *c = get_time ();
+        return true;
+      }
+
+    return false;
+  }
+
+  void do_sth();
+  void do_sth2();
+   
+  void P (int64 t)
+    {
+      int cc; /* { dg-message "note: 'cc' was declared here" } */
+      if (GetC (&cc)) /* return flag checked wrongly */
+        return;
+      
+      if (cc <= 0)  /* { dg-warning "uninitialized" "uninitialized variable warning" } */
+        {
+          this->do_sth();
+          return;
+        }
+
+    do_sth2();
+  }
+};
+
+M* m; 
+void foo(int x)
+{
+  m = new M;
+  m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C
new file mode 100644
index 000000000000..09ed69215320
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_a.C
@@ -0,0 +1,77 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+/* Multiple initialization paths.  */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int  get_time ();
+
+class A
+{
+public:
+  A ();
+  ~A () {
+    if (I) delete I;
+  }
+
+private:
+  int* I;
+};
+
+bool get_url (A *);
+bool get_url2 (A *);
+
+class M {
+
+ public:
+ __attribute__ ((always_inline))
+ bool GetC (int *c)  {
+
+    A details_str;
+    /* Intialization path 1  */
+    if (get_url (&details_str))
+      {
+        *c = get_time ();
+        return true;
+      }
+
+    /* insert dtor calls (inlined) into following return paths  */
+    A tmp_str;
+
+    /* Intializtion path 2  */
+    if (get_url2 (&details_str))
+      {
+        *c = get_time ();
+        return true;
+      }
+
+    return false;
+  }
+
+  void do_sth();
+  void do_sth2();
+
+  void P (int64 t)
+    {
+      int cc;
+      if (!GetC (&cc)) /* return flag checked properly */
+        return;
+
+      if (cc <= 0)   /* { dg-bogus "uninitialized" "uninitialized variable warning" } */
+        {
+          this->do_sth();
+          return;
+        }
+
+    do_sth2();
+  }
+};
+
+M* m;
+void test(int x)
+{
+  m = new M;
+  m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_b.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_b.C
new file mode 100644
index 000000000000..8e7b8541725e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-3_b.C
@@ -0,0 +1,87 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+/* Multiple initialization paths.  */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int  get_time ();
+
+class A
+{
+public:
+  A ();
+  ~A () {
+    if (I) delete I;
+  }
+
+private:
+  int* I;
+};
+
+bool get_url (A *);
+bool get_url2 (A *);
+bool get_url3 (A *);
+
+class M {
+
+ public:
+ __attribute__ ((always_inline))
+ bool GetC (int *c)  {
+
+    A details_str;
+
+    /* Initialization path 1  */
+    if (get_url (&details_str))
+      {
+        *c = get_time ();
+        return true;
+      }
+
+    /* Destructor call before return*/
+    A tmp_str;
+
+    /* Initialization path 2  */
+    if (get_url2 (&details_str))
+      {
+        *c = get_time ();
+        return true;
+      }
+
+    /* Fail to initialize in this path but
+       still returns true  */
+    if (get_url2 (&details_str))
+      {
+        /* Fail to initialize *c  */
+        return true;
+      }
+
+    return false;
+  }
+
+  void do_sth();
+  void do_sth2();
+
+  void P (int64 t)
+    {
+      int cc;
+      if (!GetC (&cc))
+        return;
+
+      if (cc <= 0)   /* { dg-warning "uninitialized" "uninitialized variable warning" } */
+        {
+          this->do_sth();
+          return;
+        }
+
+    do_sth2();
+  }
+};
+
+M* m;
+void test(int x)
+{
+  m = new M;
+  m->P(x);
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C b/gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C
new file mode 100644
index 000000000000..c48770ae44dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-4.C
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -Og -ftrivial-auto-var-init=zero" } */
+
+int pop ();
+int pop_first_bucket;
+
+int my_pop ()
+{
+  int out;  // { dg-bogus "uninitialized" "uninitialized variable warning" }
+
+  while (pop_first_bucket)
+    if (pop_first_bucket && (out = pop()))
+      return out;
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_a.cc b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_a.cc
new file mode 100644
index 000000000000..629677a60259
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_a.cc
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+extern int bar();
+int foo(void)
+{
+ for (;;) {
+   int err = ({int _err; /*  { dg-bogus "uninitialized" "false warning" } */
+     for (int i = 0; i < 16; ++i) {
+       _err = 17;
+       _err = bar();
+     }
+     _err; /*  { dg-bogus "uninitialized" "false warning" } */
+   });
+
+   if (err == 0) return 17; 
+ }
+
+ return 18;
+}
+
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_b.cc b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_b.cc
new file mode 100644
index 000000000000..04ab364ac83e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_b.cc
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+extern int bar();
+int foo(int n)
+{
+ for (;;) {
+   int err = ({int _err; 
+     for (int i = 0; i < n; ++i) {
+       _err = 17;
+       _err = bar();
+     }
+     _err; 
+   }); /* { dg-warning "uninitialized" "warn on _err" } */
+
+   if (err == 0) return 17; 
+ }
+
+ return 18;
+}
+
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_c.cc b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_c.cc
new file mode 100644
index 000000000000..82a1846c6e0b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop-1_c.cc
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+extern int bar();
+int foo(int n, int m)
+{
+ for (;;) {
+   int err = ({int _err; 
+     for (int i = 0; i < 16; ++i) {
+       if (m+i > n)
+          break;
+       _err = 17;
+       _err = bar();
+     }
+     _err; 
+   }); 
+
+   if (err == 0) return 17; }); /* { dg-warning "uninitialized" "warn on _err" } */
+ }
+
+ return 18;
+}
+
diff --git a/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop_1.cc b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop_1.cc
new file mode 100644
index 000000000000..629677a60259
--- /dev/null
+++ b/gcc/testsuite/g++.dg/auto-init-uninit-pred-loop_1.cc
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2 -ftrivial-auto-var-init=zero" } */
+
+extern int bar();
+int foo(void)
+{
+ for (;;) {
+   int err = ({int _err; /*  { dg-bogus "uninitialized" "false warning" } */
+     for (int i = 0; i < 16; ++i) {
+       _err = 17;
+       _err = bar();
+     }
+     _err; /*  { dg-bogus "uninitialized" "false warning" } */
+   });
+
+   if (err == 0) return 17; 
+ }
+
+ return 18;
+}
+
diff --git a/gcc/testsuite/gcc.dg/auto-init-sra-1.c b/gcc/testsuite/gcc.dg/auto-init-sra-1.c
new file mode 100644
index 000000000000..88fd66678f29
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-sra-1.c
@@ -0,0 +1,24 @@
+/* Verify that SRA total scalarization will not be confused by padding
+   and also not confused by auto initialization.  */
+/* { dg-do compile } */
+/* { dg-options "-O1 --param sra-max-scalarization-size-Ospeed=16 -fdump-tree-release_ssa -ftrivial-auto-var-init=zero" } */
+
+struct S
+{
+  int i;
+  unsigned short f1;
+  char f2;
+  unsigned short f3, f4;
+};
+
+
+int foo (struct S *p)
+{
+  struct S l;
+
+  l = *p;
+  l.i++;
+  *p = l;
+}
+
+/* { dg-final { scan-tree-dump-times "l;" 0 "release_ssa" } } */
diff --git a/gcc/testsuite/gcc.dg/auto-init-sra-2.c b/gcc/testsuite/gcc.dg/auto-init-sra-2.c
new file mode 100644
index 000000000000..d260f5ae934e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-sra-2.c
@@ -0,0 +1,24 @@
+/* Verify that SRA total scalarization will not be confused by padding
+   and also not confused by auto initialization.  */
+/* { dg-do compile } */
+/* { dg-options "-O1 --param sra-max-scalarization-size-Ospeed=16 -fdump-tree-release_ssa -ftrivial-auto-var-init=pattern" } */
+
+struct S
+{
+  int i;
+  unsigned short f1;
+  char f2;
+  unsigned short f3, f4;
+};
+
+
+int foo (struct S *p)
+{
+  struct S l;
+
+  l = *p;
+  l.i++;
+  *p = l;
+}
+
+/* { dg-final { scan-tree-dump-times "l;" 0 "release_ssa" } } */
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-1.c b/gcc/testsuite/gcc.dg/auto-init-uninit-1.c
new file mode 100644
index 000000000000..cb0e7cc62545
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-1.c
@@ -0,0 +1,30 @@
+/* Spurious uninitialized variable warnings, case 1.
+   Taken from cppfiles.c (merge_include_chains) */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+struct list
+{
+  struct list *next;
+  int id;
+};
+
+extern void free (void *);
+
+void remove_dupes (struct list *el)
+{
+  struct list *p, *q, *r;  /* { dg-bogus "r" "uninitialized variable warning" } */
+
+  for (p = el; p; p = p->next)
+  {
+    for (q = el; q != p; q = q->next)
+      if (q->id == p->id)
+      {
+	r->next = p->next;
+	free (p);
+	p = r;
+	break;
+      }
+    r = p;
+  }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-11.c b/gcc/testsuite/gcc.dg/auto-init-uninit-11.c
new file mode 100644
index 000000000000..559e2d963376
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-11.c
@@ -0,0 +1,42 @@
+/* Positive test for uninitialized variables.  */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+int sink;
+
+void f1(int parm)	/* { dg-bogus "uninitialized" "parameter" } */
+{
+  sink = parm;		/* { dg-bogus "uninitialized" "parameter" } */
+}
+
+void f2(void)
+{
+  int x;
+  sink = x;		/* { dg-warning "is used" "unconditional" } */
+}
+
+void f3(int p)
+{
+  int x;		
+  if (p)
+    x = p;
+  sink = x;            /* { dg-warning "may be used" "conditional" } */
+}
+
+void f4(int p)
+{
+  int x;		/* { dg-bogus "uninitialized" "easy if" } */
+  if (p)
+    x = 1;
+  else
+    x = 2;
+  sink = x;
+}
+
+void f5(void)
+{
+  int x, i;		/* { dg-bogus "uninitialized" "easy loop" } */
+  for (i = 0; i < 10; ++i)
+    x = 1;
+  sink = x;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-12.c b/gcc/testsuite/gcc.dg/auto-init-uninit-12.c
new file mode 100644
index 000000000000..acff725722dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-12.c
@@ -0,0 +1,12 @@
+/* PR 23497 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+typedef _Complex float C;
+C foo()
+{
+  C f;
+  __real__ f = 0;
+  __imag__ f = 0;
+  return f;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-13.c b/gcc/testsuite/gcc.dg/auto-init-uninit-13.c
new file mode 100644
index 000000000000..87dd8b587e00
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-13.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+typedef _Complex float C;
+C foo()
+{
+  C f;
+  __imag__ f = 0;
+  return f;	/* { dg-warning "is used" "unconditional" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-14.c b/gcc/testsuite/gcc.dg/auto-init-uninit-14.c
new file mode 100644
index 000000000000..592052a9e9d0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-14.c
@@ -0,0 +1,20 @@
+/* PR 24931 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+struct p {
+        short x, y;
+};
+
+struct s {
+        int i;
+        struct p p;
+};
+
+struct s f()
+{
+        struct s s;
+        s.p = (struct p){};
+        s.i = (s.p.x || s.p.y);
+        return s;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-15.c b/gcc/testsuite/gcc.dg/auto-init-uninit-15.c
new file mode 100644
index 000000000000..121f0cff274a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-15.c
@@ -0,0 +1,26 @@
+/* PR tree-optimization/17506
+   We issue an uninitialized variable warning at a wrong location at
+   line 11, which is very confusing.  Make sure we print out a note to
+   make it less confusing.  (not xfailed alternative)
+   But it is of course ok if we warn in bar about uninitialized use
+   of j.  (not xfailed alternative)  */
+/* { dg-do compile } */
+/* { dg-options "-O1 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+inline int
+foo (int i)
+{
+  if (i) /* { dg-warning "used uninitialized" } */
+    return 1;
+  return 0;
+}
+
+void baz (void);
+
+void
+bar (void)
+{
+  int j; /* { dg-message "note: 'j' was declared here" "" } */
+  for (; foo (j); ++j)  /* { dg-warning "'j' is used uninitialized" "" { xfail *-*-* } } */
+    baz ();
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-16.c b/gcc/testsuite/gcc.dg/auto-init-uninit-16.c
new file mode 100644
index 000000000000..0e4f336f726f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-16.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+int foo, bar;
+
+static
+void decode_reloc(int reloc, int *is_alt)
+{
+  if (reloc >= 20)
+      *is_alt = 1;
+  else if (reloc >= 10)
+      *is_alt = 0;
+}
+
+void testfunc()
+{
+  int alt_reloc;
+
+  decode_reloc(foo, &alt_reloc);
+
+  if (alt_reloc) /* { dg-warning "may be used uninitialized" } */
+    bar = 42;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-17.c b/gcc/testsuite/gcc.dg/auto-init-uninit-17.c
new file mode 100644
index 000000000000..9eec9440c75e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-17.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+typedef _Complex float C;
+C foo(int cond)
+{
+  C f;
+  __imag__ f = 0;
+  if (cond)
+    {
+      __real__ f = 1;
+      return f;
+    }
+  return f;	/* { dg-warning "may be used" "unconditional" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-18.c b/gcc/testsuite/gcc.dg/auto-init-uninit-18.c
new file mode 100644
index 000000000000..4922848f6dc7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-18.c
@@ -0,0 +1,24 @@
+/* { dg-do compile }  */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+char *foo(int bar, char *baz)
+{
+  char *tmp;
+
+  if (bar & 3)
+    tmp = baz;
+
+  switch (bar) {
+  case 1:
+    tmp[5] = 7;    /* { dg-bogus "may be used uninitialized" } */
+    break;
+  case 2:
+    tmp[11] = 15;  /* { dg-bogus "may be used uninitialized" } */
+    break;
+  default:
+    tmp = 0;
+    break;
+  }
+
+  return tmp;      /* { dg-bogus "may be used uninitialized" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-19.c b/gcc/testsuite/gcc.dg/auto-init-uninit-19.c
new file mode 100644
index 000000000000..38d27e4f9548
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-19.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+/* { dg-additional-options "-finline-small-functions" { target avr-*-* } } */
+
+int a, l, m;
+float *b;
+float c, d, e, g, h;
+unsigned char i, k;
+void
+fn1 (int p1, float *f1, float *f2, float *f3, unsigned char *c1, float *f4,
+     unsigned char *c2, float *p10)
+{
+  if (p1 & 8)
+    b[3] = p10[a];
+  /* { dg-warning "may be used uninitialized" "" { target { { nonpic || pie_enabled } || { hppa*64*-*-* *-*-darwin* } } } .-1 } */
+}
+
+void
+fn2 ()
+{
+  float *n;
+  if (l & 6)
+    n = &c + m;
+  fn1 (l, &d, &e, &g, &i, &h, &k, n);
+  /* { dg-warning "may be used uninitialized" "" { target { ! { { nonpic || pie_enabled } || { hppa*64*-*-* *-*-darwin* } } } } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-2.c b/gcc/testsuite/gcc.dg/auto-init-uninit-2.c
new file mode 100644
index 000000000000..da03bf8f6d98
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-2.c
@@ -0,0 +1,52 @@
+/* Spurious uninitialized variable warnings, case 2.
+   Taken from cpphash.c (macroexpand) */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+struct definition
+{
+  int nargs;
+  int rest_args;
+};
+
+struct cpp_reader;
+
+enum cpp_token
+{
+  CPP_EOF, CPP_POP, CPP_COMMA, CPP_RPAREN
+};
+
+extern enum cpp_token macarg (struct cpp_reader *, int);
+
+void
+macroexpand (struct cpp_reader *pfile, struct definition *defn)
+{
+  int nargs = defn->nargs;
+
+  if (nargs >= 0)
+    {
+      enum cpp_token token;  /* { dg-bogus "token" "uninitialized variable warning" } */
+      int i, rest_args;
+      i = 0;
+      rest_args = 0;
+      do
+	{
+	  if (rest_args)
+	    continue;
+	  if (i < nargs || (nargs == 0 && i == 0))
+	    {
+	      /* if we are working on last arg which absorbs rest of args... */
+	      if (i == nargs - 1 && defn->rest_args)
+		rest_args = 1;
+	      token = macarg (pfile, rest_args);
+	    }
+	  else
+	    token = macarg (pfile, 0);
+	  if (token == CPP_EOF || token == CPP_POP)
+	    return;
+
+	  i++;
+	}
+      while (token == CPP_COMMA);
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-20.c b/gcc/testsuite/gcc.dg/auto-init-uninit-20.c
new file mode 100644
index 000000000000..f533ce9c70e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-20.c
@@ -0,0 +1,18 @@
+/* Spurious uninitialized variable warnings, from gdb */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+struct os { struct o *o; };
+struct o { struct o *next; struct os *se; };
+void f(struct o *o){
+  struct os *s;
+  if(o) s = o->se;
+  while(o && s == o->se){
+    s++; // here `o' is non-zero and thus s is initialized
+    s == o->se  // `?' is essential, `if' does not trigger the warning
+      ? (o = o->next, o ? s = o->se : 0)
+      : 0;
+  }
+}
+
+
+
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-21.c b/gcc/testsuite/gcc.dg/auto-init-uninit-21.c
new file mode 100644
index 000000000000..6044eab27870
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-21.c
@@ -0,0 +1,33 @@
+/* PR69537, spurious warning because of a missed optimization. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-short-enums -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+enum clnt_stat {
+ RPC_SUCCESS=0,
+ RPC_CANTENCODEARGS=1,
+};
+ 
+int do_ypcall_tr ();
+ 
+static int
+yp_master (char **outname)
+{
+  // Replacing enum clnt_stat with int avoids the warning.
+  enum clnt_stat result;
+  result = do_ypcall_tr ();
+  if (result != 0)
+    return result;
+  *outname = __builtin_strdup ("foo");
+  return 0;
+}
+ 
+int
+yp_update (void)
+{
+  char *master;
+  int r;
+  if ((r = yp_master (&master)) != 0)
+    return r;
+  __builtin_free (master); /* { dg-bogus "uninitialized" } */
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-22.c b/gcc/testsuite/gcc.dg/auto-init-uninit-22.c
new file mode 100644
index 000000000000..0200d734a2c3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-22.c
@@ -0,0 +1,69 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wuninitialized --param vect-max-version-for-alias-checks=20 -ftrivial-auto-var-init=zero" } */
+
+#include <stdint.h>
+
+#define A1  2896 /* (1/sqrt(2))<<12 */
+#define A2  2217
+#define A3  3784
+#define A4 -5352
+
+#define IDCT_TRANSFORM(dest,s0,s1,s2,s3,s4,s5,s6,s7,d0,d1,d2,d3,d4,d5,d6,d7,munge,src) {\
+    const int a0 = (src)[s0] + (src)[s4]; \
+    const int a1 = (src)[s0] - (src)[s4]; \
+    const int a2 = (src)[s2] + (src)[s6]; \
+    const int a3 = (A1*((src)[s2] - (src)[s6])) >> 11; \
+    const int a4 = (src)[s5] + (src)[s3]; \
+    const int a5 = (src)[s5] - (src)[s3]; \
+    const int a6 = (src)[s1] + (src)[s7]; \
+    const int a7 = (src)[s1] - (src)[s7]; \
+    const int b0 = a4 + a6; \
+    const int b1 = (A3*(a5 + a7)) >> 11; \
+    const int b2 = ((A4*a5) >> 11) - b0 + b1; \
+    const int b3 = (A1*(a6 - a4) >> 11) - b2; \
+    const int b4 = ((A2*a7) >> 11) + b3 - b1; \
+    (dest)[d0] = munge(a0+a2   +b0); \
+    (dest)[d1] = munge(a1+a3-a2+b2); \
+    (dest)[d2] = munge(a1-a3+a2+b3); \
+    (dest)[d3] = munge(a0-a2   -b4); \
+    (dest)[d4] = munge(a0-a2   +b4); \
+    (dest)[d5] = munge(a1-a3+a2-b3); \
+    (dest)[d6] = munge(a1+a3-a2-b2); \
+    (dest)[d7] = munge(a0+a2   -b0); \
+}
+
+#define MUNGE_NONE(x) (x)
+#define IDCT_COL(dest,src) IDCT_TRANSFORM(dest,0,8,16,24,32,40,48,56,0,8,16,24,32,40,48,56,MUNGE_NONE,src)
+
+#define MUNGE_ROW(x) (((x) + 0x7F)>>8)
+#define IDCT_ROW(dest,src) IDCT_TRANSFORM(dest,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,MUNGE_ROW,src)
+
+static inline void bink_idct_col(int *dest, const int32_t *src)
+{
+    if ((src[8]|src[16]|src[24]|src[32]|src[40]|src[48]|src[56])==0) {
+        dest[0]  =
+        dest[8]  =
+        dest[16] =
+        dest[24] =
+        dest[32] =
+        dest[40] =
+        dest[48] =
+        dest[56] = src[0];
+    } else {
+        IDCT_COL(dest, src);
+    }
+}
+
+int bink_idct_put_c(uint8_t *dest, int linesize, int32_t *block)
+{
+    int i;
+    int temp[64];
+    for (i = 0; i < 8; i++)
+        bink_idct_col(&temp[i], &block[i]);
+    for (i = 0; i < 8; i++) {
+        IDCT_ROW( (&dest[i*linesize]), (&temp[8*i]) );
+    }
+
+    return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-23.c b/gcc/testsuite/gcc.dg/auto-init-uninit-23.c
new file mode 100644
index 000000000000..7dce8d052e16
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-23.c
@@ -0,0 +1,27 @@
+/* PR tree-optimization/78455 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+int ij;
+
+void
+ql (void)
+{
+  int m5 = 0;
+
+  for (;;)
+  {
+    if (0)
+      for (;;)
+      {
+        int *go;
+        int *t4 = go; /* { dg-warning "is used uninitialized" } */
+
+ l1:
+        *t4 = (*t4 != 0) ? 0 : 2;
+      }
+
+    if (ij != 0)
+      goto l1;
+  }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-24.c b/gcc/testsuite/gcc.dg/auto-init-uninit-24.c
new file mode 100644
index 000000000000..1f6740c123ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-24.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wmaybe-uninitialized -ftrivial-auto-var-init=zero" } */
+
+int foo (int x)
+{
+  int y;
+  if (x)
+    return *(&y + 1); /* { dg-bogus "may be used uninitialized" } */
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-25.c b/gcc/testsuite/gcc.dg/auto-init-uninit-25.c
new file mode 100644
index 000000000000..f36d95f9d279
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-25.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wmaybe-uninitialized -ftrivial-auto-var-init=zero" } */
+
+extern unsigned bar (void);
+extern void quux (void);
+
+unsigned foo (unsigned v)
+{
+  unsigned u;
+  if (v != 1)
+    u = bar ();
+
+  // Prevent the "dom" pass from changing the CFG layout based on the inference
+  // 'if (v != 1) is false then (v != 2) is true'.  (Now it would have to
+  // duplicate the loop in order to do so, which is deemed expensive.)
+  for (int i = 0; i < 10; i++)
+    quux ();
+
+  if (v != 2)
+    return u;       /* { dg-warning "may be used uninitialized" } */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-26.c b/gcc/testsuite/gcc.dg/auto-init-uninit-26.c
new file mode 100644
index 000000000000..ae97ecfa71e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-26.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wmaybe-uninitialized -ftrivial-auto-var-init=zero" } */
+
+extern unsigned bar (void);
+extern void quux (void);
+
+unsigned foo (unsigned v)
+{
+  unsigned u;
+  if (v != 100)
+    u = bar ();
+
+  // Prevent the "dom" pass from changing the CFG layout based on the inference
+  // 'if (v != 100) is false then (v < 105) is true'.  (Now it would have to
+  // duplicate the loop in order to do so, which is deemed expensive.)
+  for (int i = 0; i < 10; i++)
+    quux ();
+
+  if (v < 105) /* v == 100 falls into this range.  */
+    return u;       /* { dg-warning "may be used uninitialized" }  */
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-3.c b/gcc/testsuite/gcc.dg/auto-init-uninit-3.c
new file mode 100644
index 000000000000..7ff228501f8d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-3.c
@@ -0,0 +1,33 @@
+/* Spurious uninit variable warnings, case 3.
+   Inspired by cppexp.c (parse_charconst) */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+extern void error (char *);
+
+int
+parse_charconst (const char *start, const char *end)
+{
+  int c; /* { dg-bogus "c" "uninitialized variable warning" } */
+  int nchars, retval;
+
+  nchars = 0;
+  retval = 0;
+  while (start < end)
+    {
+      c = *start++;
+      if (c == '\'')
+	break;
+      nchars++;
+      retval += c;
+      retval <<= 8;
+    }
+
+  if (nchars == 0)
+    return 0;
+
+  if (c != '\'')
+    error ("malformed character constant");
+
+  return retval;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-34.c b/gcc/testsuite/gcc.dg/auto-init-uninit-34.c
new file mode 100644
index 000000000000..98fc366c871f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-34.c
@@ -0,0 +1,58 @@
+/* PR middle-end/10138 - warn for uninitialized arrays passed as const*
+   arguments
+   Verify that passing pointers to uninitialized objects to arguments
+   to functions declared with attribute access is diagnosed where expected.
+   { dg-do compile }
+   { dg-options "-O -Wall -ftrivial-auto-var-init=zero" } */
+
+#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__)))
+
+RW (1) RW (3) void
+f4pi (int*, int*, int*, int*);    // { dg-message "in a call to 'f4pi' declared with attribute 'access \\\(read_write, \[13\]\\\)'" }
+
+
+void nowarn_scalar (void)
+{
+  int i1 = 0, i2, i3 = 1, i4;
+  f4pi (&i1, &i2, &i3, &i4);
+}
+
+void warn_scalar_1 (void)
+{
+  int i1;                         // { dg-message "declared here" }
+  int i2, i3 = 1, i4;
+
+  f4pi (&i1, &i2, &i3, &i4);      // { dg-warning "'i1' may be used uninitialized" }
+}
+
+void warn_scalar_2 (void)
+{
+  int j1 = 0, j2, j4;
+  int j3;
+
+  f4pi (&j1, &j2, &j3, &j4);      // { dg-warning "'j3' may be used uninitialized" }
+}
+
+
+void nowarn_array_init (void)
+{
+  int a1[4] = { 0 }, a2[5], a3[6] = { 0 }, a4[7];
+
+  f4pi (a1, a2, a3, a4);
+}
+
+void warn_array_1 (void)
+{
+  int a1[4];                  // { dg-message "'a1' declared here" }
+  int a2[5], a3[6] = { 0 }, a4[7];
+
+  f4pi (a1, a2, a3, a4);      // { dg-warning "'a1' may be used uninitialized" }
+}
+
+void warn_array_2 (void)
+{
+  int a1[4] = { 0 }, a2[5], a4[7];
+  int a3[6];                  // { dg-message "'a3' declared here" }
+
+  f4pi (a1, a2, a3, a4);      // { dg-warning "'a3' may be used uninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-36.c b/gcc/testsuite/gcc.dg/auto-init-uninit-36.c
new file mode 100644
index 000000000000..64377d380ee9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-36.c
@@ -0,0 +1,238 @@
+/* PR middle-end/10138 - warn for uninitialized arrays passed as const*
+   arguments
+   Verify that passing pointers to uninitialized objects to const
+   arguments to built-ins is diagnosed where expected.
+   { dg-do compile }
+   { dg-options "-O -Wall -ftrivial-auto-var-init=zero" }
+   { dg-require-effective-target alloca } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* alloca (size_t);
+void* malloc (size_t);
+void* realloc (void*, size_t);
+
+void* memcpy (void*, const void*, size_t);
+char* strcpy (char*, const char*);
+size_t strlen (const char*);
+
+void sink (void*);
+
+void nowarn_array_memcpy (void *d, unsigned n)
+{
+  int a[2];
+  /* Diagnose this?  */
+  memcpy (d, a, n /* Non-constant to avoid folding into MEM_REF.  */);
+}
+
+void nowarn_array_plus_cst_memcpy (void *d, unsigned n)
+{
+  int a[3];
+  /* Diagnose this?  */
+  memcpy (d, a + 1, n);
+}
+
+void nowarn_array_plus_var_memcpy (void *d, unsigned n, int i)
+{
+  int a[4];
+  /* Diagnose this?  */
+  memcpy (d, a + i, n);
+}
+
+void nowarn_array_assign_memcpy (char *d, unsigned n)
+{
+  int a[3];
+  a[1] = 3;
+  memcpy (d, a, n);
+}
+
+void nowarn_array_init_memcpy (char *d, unsigned n)
+{
+  int a[4] = { 0 };
+  memcpy (d, a, n);
+}
+
+void nowarn_array_compound_memcpy (void *d, unsigned n)
+{
+  memcpy (d, (int[2]){ 0 }, n);
+}
+
+void nowarn_struct_assign_memcpy (void *d, unsigned n)
+{
+  struct S { int a, b, c, d; } s;
+  s.b = 1;
+  s.d = 2;
+  memcpy (d, &s, n);
+}
+
+
+void nowarn_array_init_strcpy (char *d[], unsigned n)
+{
+  char a[8] = "012";
+
+  strcpy (d[0], a);
+  strcpy (d[1], a + 1);
+  strcpy (d[1], a + 2);
+  strcpy (d[1], a + 3);
+  strcpy (d[1], a + 4);
+  strcpy (d[1], a + 5);
+  strcpy (d[1], a + 6);
+  strcpy (d[1], a + 7);
+}
+
+
+void nowarn_array_assign_strcpy (char *d[], unsigned n)
+{
+  char a[8];
+  a[0] = '0';
+  a[1] = '1';
+  a[2] = '2';
+  a[3] = '\0';
+
+  strcpy (d[0], a);
+  strcpy (d[1], a + 1);
+  strcpy (d[1], a + 2);
+  strcpy (d[1], a + 3);
+}
+
+void warn_array_plus_cst_strcpy (char *d, unsigned n)
+{
+  char a[8];
+  a[0] = '1';
+  a[1] = '2';
+  a[2] = '3';
+  a[3] = '\0';
+
+  strcpy (d, a + 4);          // { dg-warning "\\\[-Wuninitialized" }
+  strcpy (d, a + 5);          // { dg-warning "\\\[-Wuninitialized" }
+  strcpy (d, a + 6);          // { dg-warning "\\\[-Wuninitialized" }
+  strcpy (d, a + 7);          // { dg-warning "\\\[-Wuninitialized" }
+}
+
+void nowarn_array_plus_var_strcpy (char *d, int i)
+{
+  char a[8];
+  a[0] = '1';
+  a[1] = '2';
+  a[2] = '3';
+  a[3] = '\0';
+
+  strcpy (d, a + i);
+}
+
+
+size_t nowarn_array_assign_strlen (const char *s)
+{
+  char a[8];
+  a[0] = s[0];
+  a[1] = s[1];
+  a[2] = s[2];
+  a[3] = s[3];
+
+  size_t n = 0;
+
+  n += strlen (a);
+  n += strlen (a + 1);
+  n += strlen (a + 2);
+  n += strlen (a + 3);
+  return n;
+}
+
+size_t warn_array_plus_cst_strlen (const char *s)
+{
+  char a[8];
+  a[0] = s[0];
+  a[1] = s[1];
+  a[2] = s[2];
+  a[3] = s[3];
+
+  return strlen (a + 4);      // { dg-warning "\\\[-Wuninitialized" }
+}
+
+size_t nowarn_array_plus_var_strlen (const char *s, int i)
+{
+  char a[8];
+  a[0] = s[0];
+  a[1] = s[1];
+  a[2] = s[2];
+  a[3] = s[3];
+
+  return strlen (a + i);
+}
+
+
+size_t nowarn_alloca_assign_strlen (int i)
+{
+  char *p = (char*)alloca (8);
+  p[i] = '\0';
+  return strlen (p);
+}
+
+size_t nowarn_alloca_escape_strlen (int i)
+{
+  char *p = (char*)alloca (8);
+  sink (p);
+  return strlen (p);
+}
+
+size_t warn_alloca_strlen (void)
+{
+  char *p = (char*)alloca (8);
+  return strlen (p);          // { dg-warning "\\\[-Wuninitialized" }
+}
+
+
+size_t nowarn_malloc_assign_strlen (int i)
+{
+  char *p = (char*)malloc (8);
+  p[i] = '\0';
+  return strlen (p);
+}
+
+size_t nowarn_malloc_escape_strlen (int i)
+{
+  char *p = (char*)malloc (8);
+  sink (p);
+  return strlen (p);
+}
+
+size_t warn_malloc_strlen (void)
+{
+  char *p = (char*)malloc (8);
+  return strlen (p);          // { dg-warning "\\\[-Wuninitialized" }
+}
+
+
+size_t nowarn_realloc_strlen (void *p)
+{
+  char *q = (char*)realloc (p, 8);
+  return strlen (q);
+}
+
+
+size_t nowarn_vla_assign_strlen (int n, int i)
+{
+  char vla[n];
+  vla[i] = '\0';
+  return strlen (vla);
+}
+
+size_t nowarn_vla_strcpy_strlen (int n, const char *s, int i)
+{
+  char vla[n];
+  strcpy (vla, s);
+  return strlen (vla + i);
+}
+
+size_t nowarn_vla_escape_strlen (int n, int i)
+{
+  char vla[n];
+  sink (vla);
+  return strlen (vla);
+}
+
+size_t warn_vla_strlen (unsigned n)
+{
+  char vla[n];
+  return strlen (vla);        // { dg-warning "\\\[-Wuninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-37.c b/gcc/testsuite/gcc.dg/auto-init-uninit-37.c
new file mode 100644
index 000000000000..da3c9db1840a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-37.c
@@ -0,0 +1,154 @@
+/* PR middle-end/10138 - warn for uninitialized arrays passed as const arguments
+   Verify that -Wuninitialized and -Wmaybe-uninitialized trigger (or don't)
+   when passing uninitialized variables by reference to functions declared
+   with or without attribute access and with (or without) const qualified
+   arguments of array, VLA, or pointer types.
+   { dg-do compile }
+   { dg-options "-O2 -Wall -ftrack-macro-expansion=0 -ftrivial-auto-var-init=zero" } */
+
+#define NONE    /* none */
+#define RO(...) __attribute__ ((access (read_only, __VA_ARGS__)))
+#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__)))
+#define WO(...) __attribute__ ((access (write_only, __VA_ARGS__)))
+#define X(...)  __attribute__ ((access (none, __VA_ARGS__)))
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y)    CONCAT (x, y)
+#define UNIQ(pfx)    CAT (pfx, __LINE__)
+
+extern void sink (void*);
+
+
+#define T1(attr, name, type)			\
+  void UNIQ (CAT (test_, name))(void) {		\
+    extern attr void UNIQ (name)(type);		\
+    int x;					\
+    UNIQ (name)(&x);				\
+    sink (&x);					\
+  }
+
+#define T2(attr, name, types)			\
+  void UNIQ (CAT (test_, name))(void) {		\
+    extern attr void UNIQ (name)(types);	\
+    int x;					\
+    UNIQ (name)(1, &x);				\
+    sink (&x);					\
+  }
+
+
+typedef int IA_[];
+typedef const int CIA_[];
+
+T1 (NONE,   fia_,   IA_);
+T1 (NONE,   fcia_,  CIA_);    // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froia_, IA_);     // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwia_, IA_);     // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoia_, IA_);
+T1 (X (1),  fxia_,  IA_);
+
+
+typedef int IA1[1];
+typedef const int CIA1[1];
+
+T1 (NONE,   fia1,   IA1);
+T1 (NONE,   fcia1,  CIA1);    // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froia1, IA1);     // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwia1, IA1);     // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoia1, IA1);
+T1 (X (1),  fxia1,  IA1);
+
+
+#define IARS1  int[restrict static 1]
+#define CIARS1 const int[restrict static 1]
+
+T1 (NONE,   fiars1,   IARS1);
+T1 (NONE,   fciars1,  CIARS1);// { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froiars1, IARS1); // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwiars1, IARS1); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoiars1, IARS1);
+T1 (X (1),  fxiars1,  IARS1);
+
+
+#define IAS1  int[static 1]
+#define CIAS1 const int[static 1]
+
+T1 (NONE,   fias1,   IAS1);
+T1 (NONE,   fcias1,  CIAS1);   // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froias1, IAS1);    // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwias1, IAS1);    // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoias1, IAS1);
+T1 (X (1),  fxias1,  IAS1);
+
+
+#define IAX  int[*]
+#define CIAX const int[*]
+
+T1 (NONE,   fiax,   IAX);
+T1 (NONE,   fciax,  CIAX);    // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froiax, IAX);     // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwiax, IAX);     // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoiax, IAX);
+T1 (X (1),  fxiax,  IAX);
+
+
+#define IAN  int n, int[n]
+#define CIAN int n, const int[n]
+
+T2 (NONE,      fian,   IAN);
+T2 (NONE,      fcian,  CIAN); // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T2 (RO (2, 1), froian, IAN);  // { dg-warning "\\\[-Wuninitialized" }
+T2 (RW (2, 1), frwian, IAN);  // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T2 (WO (2, 1), fwoian, IAN);
+T2 (X (2, 1),  fxian,  IAN);
+
+
+typedef int* IP;
+typedef const int* CIP;
+
+T1 (NONE,   fip,   IP);
+T1 (NONE,   fcip,  CIP);     // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (RO (1), froip, IP);      // { dg-warning "\\\[-Wuninitialized" }
+T1 (RW (1), frwip, IP);      // { dg-warning "\\\[-Wmaybe-uninitialized" }
+T1 (WO (1), fwoip, IP);
+T1 (X (1),  fxip,  IP);
+
+
+/* Verify that the notes printed after the warning mention attribute
+   access only when the attribute is explicitly used in the declaration
+   and not otherwise.  */
+
+void test_note_cst_restrict (void)
+{
+  extern void
+    fccar (const char[restrict]);   // { dg-message "by argument 1 of type 'const char\\\[restrict]' to 'fccar'" "note" }
+
+  char a[1];                  // { dg-message "'a' declared here" "note" }
+  fccar (a);                  // { dg-warning "'a' may be used uninitialized" }
+}
+
+void test_note_vla (int n)
+{
+  extern void
+    fccvla (const char[n]);   // { dg-message "by argument 1 of type 'const char\\\[n]' to 'fccvla'" "note" }
+
+  char a[2];                  // { dg-message "'a' declared here" "note" }
+  fccvla (a);                 // { dg-warning "'a' may be used uninitialized" }
+}
+
+void test_note_ro (void)
+{
+  extern RO (1) void
+    frocar (char[restrict]);  // { dg-message "in a call to 'frocar' declared with attribute 'access \\\(read_only, 1\\\)'" "note" }
+
+  char a[3];                  // { dg-message "'a' declared here" "note" }
+  frocar (a);                 // { dg-warning "'a' is used uninitialized" }
+}
+
+void test_note_rw (void)
+{
+  extern RW (1) void
+    frwcar (char[restrict]);  // { dg-message "in a call to 'frwcar' declared with attribute 'access \\\(read_write, 1\\\)'" "note" }
+
+  char a[4];                  // { dg-message "'a' declared here" "note" }
+  frwcar (a);                 // { dg-warning "'a' may be used uninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-4.c b/gcc/testsuite/gcc.dg/auto-init-uninit-4.c
new file mode 100644
index 000000000000..482c837cacb2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-4.c
@@ -0,0 +1,52 @@
+/* Spurious uninit variable warnings, case 4.
+   Simplified version of cppexp.c (cpp_parse_expr).
+
+   This one is really fragile, it gets it right if you take out case
+   1, or if the structure is replaced by an int, or if the structure
+   has fewer members (!) */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+extern void abort (void);
+
+struct operation {
+    short op;
+    char rprio;
+    char flags;
+    char unsignedp;
+    long value;
+};
+
+extern struct operation cpp_lex (void);
+
+void
+cpp_parse_expr (void)
+{
+  int rprio; /* { dg-bogus "rprio" "uninitialized variable warning PR19833" } */
+  struct operation op;
+
+  for (;;)
+    {
+      op = cpp_lex ();
+
+      switch (op.op)
+	{
+	case 0:
+	  break;
+	case 1:
+	  return;
+	case 2:
+	  rprio = 1;
+	  break;
+	default:
+	  return;
+	}
+
+      if (op.op == 0)
+	return;
+
+      if (rprio != 1)
+	abort();
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-5.c b/gcc/testsuite/gcc.dg/auto-init-uninit-5.c
new file mode 100644
index 000000000000..ada81c912bdd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-5.c
@@ -0,0 +1,39 @@
+/* Spurious uninitialized-variable warnings.  */
+/* Disable jump threading, etc to test compiler analysis.  */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -fno-tree-dce -fno-tree-vrp -fno-tree-dominator-opts -ftrivial-auto-var-init=zero" } */
+
+extern void use(int);
+extern void foo(void);
+
+void
+func1(int cond)
+{
+    int x;  /* { dg-bogus "x" "uninitialized variable warning" } */
+
+    if(cond)
+	x = 1;
+
+    foo();
+
+    if(cond)
+	use(x);
+}
+
+void
+func2 (int cond)
+{
+    int x;  /* { dg-bogus "x" "uninitialized variable warning" } */
+    int flag = 0;
+
+    if(cond)
+    {
+	x = 1;
+	flag = 1;
+    }
+
+    foo();
+
+    if(flag)
+	use(x);
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-6.c b/gcc/testsuite/gcc.dg/auto-init-uninit-6.c
new file mode 100644
index 000000000000..e6cba4ef22c0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-6.c
@@ -0,0 +1,47 @@
+/* Spurious uninitialized variable warnings.
+   This one inspired by java/class.c:build_utf8_ref.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+#include <stddef.h>
+
+struct tree
+{
+    struct tree *car;
+    struct tree *cdr;
+    int type, data;
+};
+
+extern void *malloc(size_t);
+
+#define INTEGER_T 1
+#define PTR_T	  2
+
+#define APPEND(TREE, LAST, TYPE, VALUE)				\
+do {								\
+     struct tree *tmp = malloc (sizeof (struct tree));		\
+     tmp->car = 0; tmp->cdr = 0; tmp->type = TYPE;		\
+     tmp->data = VALUE;						\
+     if (TREE->car)						\
+	 LAST->cdr = tmp;					\
+     else							\
+	 TREE->car = tmp;					\
+     LAST = tmp;						\
+} while(0)
+ 
+struct tree *
+make_something(int a, int b, int c)
+{
+    struct tree *rv;
+    struct tree *field;
+
+    rv = malloc (sizeof (struct tree));
+    rv->car = 0;
+
+    APPEND(rv, field, INTEGER_T, a);  /* { dg-bogus "field" "uninitialized variable warning" } */
+    APPEND(rv, field, PTR_T, b);
+    APPEND(rv, field, INTEGER_T, c);
+
+    return rv;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-8.c b/gcc/testsuite/gcc.dg/auto-init-uninit-8.c
new file mode 100644
index 000000000000..6c298870c679
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-8.c
@@ -0,0 +1,32 @@
+/* Uninitialized variable warning tests...
+   Inspired by part of optabs.c:expand_binop.
+   May be the same as uninit-1.c.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+#include <limits.h>
+
+void
+add_bignums (int *out, int *x, int *y)
+{
+    int p, sum;
+    int carry; /* { dg-bogus "carry" "uninitialized variable warning" } */
+
+    p = 0;
+    for (; *x; x++, y++, out++, p++)
+    {
+	if (p)
+	    sum = *x + *y + carry;
+	else
+	    sum = *x + *y;
+
+	if (sum < 0)
+	{
+	    carry = 1;
+	    sum -= INT_MAX;
+	}
+	else
+	    carry = 0;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-9.c b/gcc/testsuite/gcc.dg/auto-init-uninit-9.c
new file mode 100644
index 000000000000..9d65493bde2a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-9.c
@@ -0,0 +1,42 @@
+/* Spurious uninitialized variable warnings.  Slight variant on the
+   documented case, inspired by reg-stack.c:record_asm_reg_life.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+/* { dg-require-effective-target alloca } */
+
+struct foo
+{
+    int type;
+    struct foo *car;
+    struct foo *cdr;
+    char *data;
+    int data2;
+};
+
+extern void use(struct foo *);
+
+#define CLOBBER 6
+#define PARALLEL 3
+
+void
+func(struct foo *list, int count)
+{
+    int n_clobbers = 0;
+    int i;
+    struct foo **clob_list;   /* { dg-bogus "clob_list" "uninitialized variable warning" } */
+
+    if(list[0].type == PARALLEL)
+    {
+	clob_list = __builtin_alloca(count * sizeof(struct foo *));
+	
+	for(i = 1; i < count; i++)
+	{
+	    if(list[i].type == CLOBBER)
+		clob_list[n_clobbers++] = &list[i];
+	}
+    }
+
+    for(i = 0; i < n_clobbers; i++)
+	use(clob_list[i]);
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-A.c b/gcc/testsuite/gcc.dg/auto-init-uninit-A.c
new file mode 100644
index 000000000000..01fcf59f4504
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-A.c
@@ -0,0 +1,117 @@
+/* Inspired by part of java/parse.y.
+   May be a real bug in CSE. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -ftrivial-auto-var-init=zero" } */
+
+struct tree
+{
+    struct tree *car, *cdr, *wfl;
+    int code;
+    struct { unsigned int renp:1;
+      unsigned int rtnp:1;
+      unsigned int rpnp:1; } flags;
+};
+typedef struct tree *tree;
+#define NULL_TREE ((tree)0)
+
+/* Codes */
+enum
+{
+    CALL_EXPR, NEW_ARRAY_EXPR, NEW_CLASS_EXPR, CONVERT_EXPR,
+    ARRAY_REF, CONDITIONAL_EXPR, STRING_CST, EXPR_WITH_FILE_LOCATION
+};
+
+/* Flags */
+#define RESOLVE_EXPRESSION_NAME_P(t) ((t)->flags.renp)
+#define RESOLVE_TYPE_NAME_P(t) ((t)->flags.rtnp)
+#define RESOLVE_PACKAGE_NAME_P(t) ((t)->flags.rpnp)
+
+/* Macros */
+#define EXPR_WFL_QUALIFICATION(t) ((t)->wfl)
+#define QUAL_WFL(t) ((t)->wfl)
+#define EXPR_WFL_NODE(t) ((t)->wfl)
+#define TREE_CODE(t) ((t)->code)
+#define TREE_OPERAND(t,x) ((t)->car)
+#define CLASSTYPE_SUPER(t) ((t)->car)
+#define IDENTIFIER_LOCAL_VALUE(t) ((t)->car)
+#define TREE_CHAIN(t) ((t)->cdr)
+#define QUAL_RESOLUTION(t) ((t)->cdr)
+
+extern tree current_class, this_identifier_node;
+extern tree super_identifier_node, length_identifier_node;
+
+tree resolve_and_layout (tree, tree);
+tree lookup_field_wrapper (tree, tree);
+
+void
+qualify_ambiguous_name (id)
+     tree id;
+{
+  tree qual, qual_wfl, decl;
+  tree name;	 /* { dg-bogus "name" "uninitialized variable warning" } */
+  tree ptr_type; /* { dg-bogus "ptr_type" "uninitialized variable warning" } */
+  int again, new_array_found = 0;
+  int super_found = 0, this_found = 0;
+
+  qual = EXPR_WFL_QUALIFICATION (id);
+  do {
+    qual_wfl = QUAL_WFL (qual);
+    switch (TREE_CODE (qual_wfl))
+      {
+      case CALL_EXPR:
+	qual_wfl = TREE_OPERAND (qual_wfl, 0);
+	if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION)
+	  {
+	    qual = EXPR_WFL_QUALIFICATION (qual_wfl);
+	    qual_wfl = QUAL_WFL (qual);
+	  }
+	break;
+      case NEW_ARRAY_EXPR:
+	qual = TREE_CHAIN (qual);
+	new_array_found = again = 1;
+	continue;
+      case NEW_CLASS_EXPR:
+      case CONVERT_EXPR:
+	qual_wfl = TREE_OPERAND (qual_wfl, 0);
+	break;
+      case ARRAY_REF:
+	while (TREE_CODE (qual_wfl) == ARRAY_REF)
+	  qual_wfl = TREE_OPERAND (qual_wfl, 0);
+	break;
+      default:
+	break;
+      }
+
+    name = EXPR_WFL_NODE (qual_wfl);
+    ptr_type = current_class;
+    again = 0;
+
+  } while (again);
+
+  /* If you put straightforward uses of name and ptr_type here
+     instead of the if-else sequence below, the warnings go away.
+     Therefore I suspect a real bug. */
+  
+  if (!this_found && !super_found && (decl = IDENTIFIER_LOCAL_VALUE (name)))
+    {
+      RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
+      QUAL_RESOLUTION (qual) = decl;
+    }
+  else if ((decl = lookup_field_wrapper (ptr_type, name))
+	   || (new_array_found && name == length_identifier_node))
+    {
+      RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
+      QUAL_RESOLUTION (qual) = (new_array_found ? NULL_TREE : decl);
+    }
+  else if ((decl = resolve_and_layout (name, NULL_TREE)))
+    {
+      RESOLVE_TYPE_NAME_P (qual_wfl) = 1;
+      QUAL_RESOLUTION (qual) = decl;
+    }
+  else if (TREE_CODE (QUAL_WFL (qual)) == CALL_EXPR
+	   || TREE_CODE (QUAL_WFL (qual)) == ARRAY_REF)
+    RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
+  else 
+    RESOLVE_PACKAGE_NAME_P (qual_wfl) = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-B.c b/gcc/testsuite/gcc.dg/auto-init-uninit-B.c
new file mode 100644
index 000000000000..0b2837127209
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-B.c
@@ -0,0 +1,15 @@
+/* Origin: PR c/179 from Gray Watson <gray@256.com>, adapted as a testcase
+   by Joseph Myers <jsm28@cam.ac.uk>.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+extern void foo (int *);
+extern void bar (int);
+
+void
+baz (void)
+{
+  int i;
+  if (i) /* { dg-warning "is used uninitialized" "uninit i warning" } */
+    bar (i);
+  foo (&i);
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-C.c b/gcc/testsuite/gcc.dg/auto-init-uninit-C.c
new file mode 100644
index 000000000000..a4aa629bf930
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-C.c
@@ -0,0 +1,21 @@
+/* Spurious uninitialized variable warning, inspired by libgcc2.c.  */
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+/* Not all platforms support TImode integers.  */
+#if defined(__LP64__) && !defined(__hppa__)
+typedef int TItype __attribute__ ((mode (TI)));
+#else
+typedef long TItype;
+#endif
+
+
+TItype
+__subvdi3 (TItype a, TItype b)
+{
+  TItype w;
+  
+  w = a - b;
+  
+  return w;
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-H.c b/gcc/testsuite/gcc.dg/auto-init-uninit-H.c
new file mode 100644
index 000000000000..71e2e2d68d7f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-H.c
@@ -0,0 +1,33 @@
+/* PR 14204 */
+/* { dg-do compile } */
+/* { dg-options "-O -Wall -Werror -ftrivial-auto-var-init=zero" } */
+
+#if defined __alpha__
+# define ASM __asm__("$30")
+#elif defined __i386__
+# define ASM __asm__("esp")
+#elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) || defined (_POWER)
+# define ASM __asm__("r1")
+#elif defined __s390__
+# define ASM __asm__("r15")
+#elif defined __mips
+# define ASM __asm__("$sp")
+#elif defined __sparc__
+# define ASM __asm__("sp")
+#elif defined __ia64__
+# define ASM __asm__("r12")
+#elif defined __hppa__
+# define ASM __asm__("%r30")
+#elif defined __xtensa__
+# define ASM __asm__("sp")
+#else
+/* The register name should be target-dependent so for other targets,
+   we just silence the test.  */
+# define ASM = 0
+#endif
+
+void *load_PCB (void)
+{
+  register void *sp ASM;
+  return sp;			/* { dg-bogus "uninitialized" } */
+}
diff --git a/gcc/testsuite/gcc.dg/auto-init-uninit-I.c b/gcc/testsuite/gcc.dg/auto-init-uninit-I.c
new file mode 100644
index 000000000000..09680fe9790d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/auto-init-uninit-I.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized -ftrivial-auto-var-init=zero" } */
+
+int sys_msgctl (void)
+{
+  struct { int mode; } setbuf;
+  return setbuf.mode;  /* { dg-warning "'setbuf\.mode' is used" } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-1.c b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c
new file mode 100644
index 000000000000..0fa470880bf5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for integer and pointer type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+  N1 = 0,
+  N2,
+  N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+  char temp1;
+  short temp2;
+  int temp3;
+  enum E temp4;
+  long temp5;
+  long long temp6;
+  int *temp7;
+  bool temp8;
+
+  bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+  return;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 11 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-2.c b/gcc/testsuite/gcc.target/aarch64/auto-init-2.c
new file mode 100644
index 000000000000..2c54e6d60382
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-2.c
@@ -0,0 +1,35 @@
+/* Verify pattern initialization for integer and pointer type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-O -ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+  N1 = 0,
+  N2,
+  N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+  char temp1;
+  short temp2;
+  int temp3;
+  enum E temp4;
+  long temp5;
+  long long temp6;
+  int *temp7;
+  bool temp8;
+
+  bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+  return;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfe\\\]" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffefe" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 2 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefe" 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-3.c b/gcc/testsuite/gcc.target/aarch64/auto-init-3.c
new file mode 100644
index 000000000000..1adc147a3000
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-3.c
@@ -0,0 +1,17 @@
+/* Verify zero initialization for floating point type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+long double result;
+
+long double foo()
+{
+  float temp1;
+  double temp2;
+  long double temp3;
+  
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 7 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-4.c b/gcc/testsuite/gcc.target/aarch64/auto-init-4.c
new file mode 100644
index 000000000000..9ee8335065f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-4.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for floating point type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-O -ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+long double result;
+
+long double foo()
+{
+  float temp1;
+  double temp2;
+  long double temp3;
+  
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump "fefefefe" "expand" } } */
+/* { dg-final { scan-rtl-dump "fefefefefefefefe" "expand" } } */
+/* { dg-final { scan-rtl-dump "fefefefefefefefefefefefefefefefe" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-5.c b/gcc/testsuite/gcc.target/aarch64/auto-init-5.c
new file mode 100644
index 000000000000..1874d961d5de
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-5.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for complex type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+  _Complex float temp1;
+  _Complex double temp2;
+  _Complex long double temp3;
+
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 12 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-6.c b/gcc/testsuite/gcc.target/aarch64/auto-init-6.c
new file mode 100644
index 000000000000..27c16b336789
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-6.c
@@ -0,0 +1,18 @@
+/* Verify pattern initialization for complex type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+  _Complex float temp1;
+  _Complex double temp2;
+  _Complex long double temp3;
+
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 3 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-7.c b/gcc/testsuite/gcc.target/aarch64/auto-init-7.c
new file mode 100644
index 000000000000..ac27fbe92f4a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-7.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for array, union, and structure type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+struct S
+{
+  int f1;
+  float f2;
+  char f3[20];
+};
+
+union U
+{
+  char u1[5];
+  int u2;
+  float u3; 
+};
+
+double result;
+
+double foo()
+{
+  int temp1[3];
+  double temp2[3];
+  struct S temp3;
+  union U temp4;
+  
+  result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 8 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-8.c b/gcc/testsuite/gcc.target/aarch64/auto-init-8.c
new file mode 100644
index 000000000000..3943f5a4d6b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-8.c
@@ -0,0 +1,32 @@
+/* Verify pattern initialization for array, union, and structure type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct S
+{
+  int f1;
+  float f2;
+  char f3[20];
+};
+
+union U
+{
+  char u1[5];
+  int u2;
+  float u3; 
+};
+
+double result;
+
+double foo()
+{
+  int temp1[3];
+  double temp2[3];
+  struct S temp3;
+  union U temp4;
+  
+  result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 4 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-1.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-1.c
new file mode 100644
index 000000000000..d3a88c724545
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-1.c
@@ -0,0 +1,17 @@
+/* Verify zero initialization for structure type automatic variables with
+   padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+        int internal1;
+        long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+  struct test_aligned var;
+  return var.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-10.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-10.c
new file mode 100644
index 000000000000..b0f3acb2f528
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-10.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for array type with structure element with
+   padding.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+  struct test_trailing_hole var[10]; 
+  return var[2].four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-11.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-11.c
new file mode 100644
index 000000000000..02f7edc51008
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-11.c
@@ -0,0 +1,27 @@
+/* Verify zero initialization for union type with structure field with
+   padding.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+  struct test_trailing_hole u1;
+  long long u2;
+};
+
+
+int foo ()
+{
+  union test_union_padding var;
+  return var.u1.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-12.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-12.c
new file mode 100644
index 000000000000..555972f1728f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-12.c
@@ -0,0 +1,27 @@
+/* Verify pattern initialization for union type with structure field with
+   padding.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+  struct test_trailing_hole u1;
+  long long u2;
+};
+
+
+int foo ()
+{
+  union test_union_padding var;
+  return var.u1.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-2.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-2.c
new file mode 100644
index 000000000000..aceceb87fbe1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-2.c
@@ -0,0 +1,18 @@
+/* Verify pattern initialization for structure type automatic variables with
+   padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_aligned {
+        int internal1;
+        long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+  struct test_aligned var;
+  return var.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 2 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-3.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-3.c
new file mode 100644
index 000000000000..085c38629210
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-3.c
@@ -0,0 +1,27 @@
+/* Verify zero initialization for nested structure type automatic variables with
+   padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+        unsigned internal1;
+        unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+        char one;
+        char two;
+        char three;
+        /* 61 byte padding hole here. */
+        struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+  struct test_big_hole var;
+  return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 4 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-4.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-4.c
new file mode 100644
index 000000000000..7a6ddbc20ee1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-4.c
@@ -0,0 +1,27 @@
+/* Verify pattern initialization for nested structure type automatic variables with
+   padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_aligned {
+        unsigned internal1;
+        unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+        char one;
+        char two;
+        char three;
+        /* 61 byte padding hole here. */
+        struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+  struct test_big_hole var;
+  return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 5 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-5.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-5.c
new file mode 100644
index 000000000000..3c45a6c6288d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-5.c
@@ -0,0 +1,22 @@
+/* Verify zero initialization for structure type automatic variables with
+   tail padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+        char *one;
+        char *two;
+        char *three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+  struct test_trailing_hole var;
+  return var.four;
+}
+
+/* { dg-final { scan-assembler-times "stp\txzr, xzr," 2 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-6.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-6.c
new file mode 100644
index 000000000000..bfef23d52a10
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-6.c
@@ -0,0 +1,20 @@
+/* Verify pattern initialization for structure type automatic variables with
+   tail padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_trailing_hole {
+        char *one;
+        char *two;
+        char *three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+  struct test_trailing_hole var;
+  return var.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe\\\]\\\) repeated x16" 1 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-7.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-7.c
new file mode 100644
index 000000000000..cb96c3a1e4b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-7.c
@@ -0,0 +1,20 @@
+/* Verify zero initialization for structure type automatic variables with
+   padding and has explicit initialization.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+  struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+  return var.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-8.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-8.c
new file mode 100644
index 000000000000..ce7c7cd31c1f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-8.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for structure type automatic variables with
+   padding and has explicit initialization.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+  struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+  return var.four;
+}
+
+/* { dg-final { scan-assembler "stp\txzr, xzr," } } */
+
+
diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-padding-9.c b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-9.c
new file mode 100644
index 000000000000..c81e5ff28b0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/auto-init-padding-9.c
@@ -0,0 +1,21 @@
+/* Verify zero initialization for array type with structure element with
+   padding.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+  struct test_trailing_hole var[10]; 
+  return var[2].four;
+}
+
+/* { dg-final { scan-assembler-times "stp\tq0, q0," 5 } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-1.c b/gcc/testsuite/gcc.target/i386/auto-init-1.c
new file mode 100644
index 000000000000..b7690df24060
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-1.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for integer and pointer type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+  N1 = 0,
+  N2,
+  N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+  char temp1;
+  short temp2;
+  int temp3;
+  enum E temp4;
+  long temp5;
+  long long temp6;
+  int *temp7;
+  bool temp8;
+
+  bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+  return;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 10 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-2.c b/gcc/testsuite/gcc.target/i386/auto-init-2.c
new file mode 100644
index 000000000000..e76fc2565168
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-2.c
@@ -0,0 +1,36 @@
+/* Verify pattern initialization for integer and pointer type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+enum E {
+  N1 = 0,
+  N2,
+  N3
+};
+
+extern void bar (char, short, int, enum E, long, long long, int *, bool);
+
+void foo()
+{
+  char temp1;
+  short temp2;
+  int temp3;
+  enum E temp4;
+  long temp5;
+  long long temp6;
+  int *temp7;
+  bool temp8;
+
+  bar (temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8);
+  return;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffffe" 2 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffffffefe" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 2 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefe" 3 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-21.c b/gcc/testsuite/gcc.target/i386/auto-init-21.c
new file mode 100644
index 000000000000..1192a908f9df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-21.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+  int arr[n];
+  bar (arr[2]);
+  return;
+}
+
+/* { dg-final { scan-rtl-dump "__builtin_memset" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-22.c b/gcc/testsuite/gcc.target/i386/auto-init-22.c
new file mode 100644
index 000000000000..431d9664e94f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-22.c
@@ -0,0 +1,14 @@
+/* Verify zero initialization for VLA automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+extern void bar (int);
+
+void foo(int n)
+{
+  int arr[n];
+  bar (arr[2]);
+  return;
+}
+
+/* { dg-final { scan-rtl-dump "__builtin_memset" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-23.c b/gcc/testsuite/gcc.target/i386/auto-init-23.c
new file mode 100644
index 000000000000..72094f6bdb92
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-23.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+void g(void *);
+
+void foo(int a)
+{
+  int x[a][a];
+  g(x);
+}
+
+/* { dg-final { scan-rtl-dump "__builtin_memset" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-24.c b/gcc/testsuite/gcc.target/i386/auto-init-24.c
new file mode 100644
index 000000000000..5cc3a756a1c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-24.c
@@ -0,0 +1,13 @@
+/* Verify the auto initialization of nested VLA.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+void g(void *);
+
+void foo(int a)
+{
+  int x[a][a];
+  g(x);
+}
+
+/* { dg-final { scan-rtl-dump "__builtin_memset" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-3.c b/gcc/testsuite/gcc.target/i386/auto-init-3.c
new file mode 100644
index 000000000000..130e55fe2e84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-3.c
@@ -0,0 +1,17 @@
+/* Verify zero initialization for floating point type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+long double result;
+
+long double foo()
+{
+  float temp1;
+  double temp2;
+  long double temp3;
+
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 3 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-4.c b/gcc/testsuite/gcc.target/i386/auto-init-4.c
new file mode 100644
index 000000000000..55125b537bbd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-4.c
@@ -0,0 +1,20 @@
+/* Verify pattern initialization for floating point type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+long double result;
+
+long double foo()
+{
+  float temp1;
+  double temp2;
+  long double temp3;
+
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefefefefefefefefefe" 1 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-5.c b/gcc/testsuite/gcc.target/i386/auto-init-5.c
new file mode 100644
index 000000000000..06c15bf935b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-5.c
@@ -0,0 +1,20 @@
+/* Verify zero initialization for complex type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+  _Complex float temp1;
+  _Complex double temp2;
+  _Complex long double temp3;
+
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 4 "expand" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-6.c b/gcc/testsuite/gcc.target/i386/auto-init-6.c
new file mode 100644
index 000000000000..80bd56bcb9a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-6.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for complex type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+
+_Complex long double result;
+
+_Complex long double foo()
+{
+  _Complex float temp1;
+  _Complex double temp2;
+  _Complex long double temp3;
+
+  result = temp1 + temp2 + temp3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefefefefefefefefefe" 3 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-7.c b/gcc/testsuite/gcc.target/i386/auto-init-7.c
new file mode 100644
index 000000000000..e91a024631da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-7.c
@@ -0,0 +1,32 @@
+/* Verify zero initialization for array, union, and structure type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */
+
+struct S
+{
+  int f1;
+  float f2;
+  char f3[20];
+};
+
+union U
+{
+  char u1[5];
+  int u2;
+  float u3; 
+};
+
+double result;
+
+double foo()
+{
+  int temp1[3];
+  double temp2[3];
+  struct S temp3;
+  union U temp4;
+  
+  result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "const_int 0" 7 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-8.c b/gcc/testsuite/gcc.target/i386/auto-init-8.c
new file mode 100644
index 000000000000..55e55be3bdd2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-8.c
@@ -0,0 +1,35 @@
+/* Verify pattern initialization for array, union, and structure type automatic variables.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct S
+{
+  int f1;
+  float f2;
+  char f3[20];
+};
+
+union U
+{
+  char u1[5];
+  int u2;
+  float u3; 
+};
+
+double result;
+
+double foo()
+{
+  int temp1[3];
+  double temp2[3];
+  struct S temp3;
+  union U temp4;
+  
+  result = temp1[2] + temp2[1] + temp3.f2 + temp4.u3;
+  return result;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfffffffffefefefe" 1 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "\\\[0xfefefefefefefefe\\\]" 3 "expand" } } */
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefefefefefefefefefe" 3 "expand" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-1.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-1.c
new file mode 100644
index 000000000000..b4069797d939
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-1.c
@@ -0,0 +1,19 @@
+/* Verify zero initialization for structure type automatic variables with
+   padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+        int internal1;
+        long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+  struct test_aligned var;
+  return var.internal1;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 8 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-10.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-10.c
new file mode 100644
index 000000000000..af7a6028c5ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-10.c
@@ -0,0 +1,21 @@
+/* Verify pattern initialization for array type with structure element with
+   padding.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+  struct test_trailing_hole var[10]; 
+  return var[2].four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefefefefefefefefefe" 10 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-11.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-11.c
new file mode 100644
index 000000000000..31a3ee1fe971
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-11.c
@@ -0,0 +1,26 @@
+/* Verify zero initialization for union type with structure field with
+   padding.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+  struct test_trailing_hole u1;
+  long long u2;
+};
+
+
+int foo ()
+{
+  union test_union_padding var;
+  return var.u1.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-12.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-12.c
new file mode 100644
index 000000000000..bf9ea5d629a3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-12.c
@@ -0,0 +1,26 @@
+/* Verify pattern initialization for union type with structure field with
+   padding.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+union test_union_padding {
+  struct test_trailing_hole u1;
+  long long u2;
+};
+
+
+int foo ()
+{
+  union test_union_padding var;
+  return var.u1.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefefefefefefefefefe" 1 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-2.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-2.c
new file mode 100644
index 000000000000..2dc2d035a6c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-2.c
@@ -0,0 +1,19 @@
+/* Verify pattern initialization for structure type automatic variables with
+   padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_aligned {
+        int internal1;
+        long long internal2;
+} __attribute__ ((aligned(64)));
+
+int foo ()
+{
+  struct test_aligned var;
+  return var.internal1;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefefefefefefefefefe" 4 "expand" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c
new file mode 100644
index 000000000000..8a6d764b9fa4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-3.c
@@ -0,0 +1,30 @@
+/* Verify zero initialization for nested structure type automatic variables with
+   padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_aligned {
+        unsigned internal1;
+        unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+        char one;
+        char two;
+        char three;
+        /* 61 byte padding hole here. */
+        struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+  struct test_big_hole var;
+  return var.four.internal1;
+}
+
+/* { dg-final { scan-assembler "movl\t\\\$0," } } */
+/* { dg-final { scan-assembler "movl\t\\\$16," } } */
+/* { dg-final { scan-assembler "rep stosq" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-4.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-4.c
new file mode 100644
index 000000000000..1ad60243aa4c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-4.c
@@ -0,0 +1,28 @@
+/* Verify pattern initialization for nested structure type automatic variables with
+   padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_aligned {
+        unsigned internal1;
+        unsigned long long internal2;
+} __attribute__ ((aligned(64)));
+
+struct test_big_hole {
+        char one;
+        char two;
+        char three;
+        /* 61 byte padding hole here. */
+        struct test_aligned four;
+} __attribute__ ((aligned(64)));
+
+
+int foo ()
+{
+  struct test_big_hole var;
+  return var.four.internal1;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefefefefefefefefefe" 8 "expand" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-5.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-5.c
new file mode 100644
index 000000000000..e18bc3073e18
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-5.c
@@ -0,0 +1,22 @@
+/* Verify zero initialization for structure type automatic variables with
+   tail padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+        char *one;
+        char *two;
+        char *three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+  struct test_trailing_hole var;
+  return var.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 4 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-6.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-6.c
new file mode 100644
index 000000000000..738a340efb61
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-6.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for structure type automatic variables with
+   tail padding.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */
+
+struct test_trailing_hole {
+        char *one;
+        char *two;
+        char *three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+  struct test_trailing_hole var;
+  return var.four;
+}
+
+/* { dg-final { scan-rtl-dump-times "0xfefefefefefefefefefefefefefefefe" 2 "expand" } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c
new file mode 100644
index 000000000000..b5abffb0fc66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-7.c
@@ -0,0 +1,22 @@
+/* Verify zero initialization for structure type automatic variables with
+   padding and has explicit initialization.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+  struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+  return var.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 2 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c
new file mode 100644
index 000000000000..66591cff4488
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-8.c
@@ -0,0 +1,22 @@
+/* Verify pattern initialization for structure type automatic variables with
+   padding and has explicit initialization.  */
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+int foo ()
+{
+  struct test_trailing_hole var = {.one = 1,.two = 2, .four = 'c'};
+  return var.four;
+}
+
+/* { dg-final { scan-assembler-times "movq\t\\\$0," 2 } } */
+
+
diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c
new file mode 100644
index 000000000000..40fccadf920d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c
@@ -0,0 +1,23 @@
+/* Verify zero initialization for array type with structure element with
+   padding.  */ 
+/* { dg-do compile } */
+/* { dg-options "-ftrivial-auto-var-init=zero" } */
+
+struct test_trailing_hole {
+        int one;
+        int two;
+        int three;
+        char four;
+        /* "sizeof(unsigned long) - 1" byte padding hole here. */
+};
+
+
+int foo ()
+{
+  struct test_trailing_hole var[10]; 
+  return var[2].four;
+}
+
+/* { dg-final { scan-assembler "movl\t\\\$0," } } */
+/* { dg-final { scan-assembler "movl\t\\\$20," } } */
+/* { dg-final { scan-assembler "rep stosq" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index c8b0f7b33e12..8d3187d19665 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3457,31 +3457,92 @@ verify_gimple_call (gcall *stmt)
 	}
     }
 
+  /* For a call to .DEFERRED_INIT, we should guarantee that the 1st and the 3rd
+     argument is consistent, i.e.:
+     1st argument: SIZE of the DECL;
+     3rd argument: IS_VLA, 0 NO, 1 YES;
+
+     if IS_VLA is false, the 1st argument should be a constant and the same as
+     the size of the LHS.  */
+  if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+    {
+      tree size_of_arg0 = gimple_call_arg (stmt, 0);
+      tree size_of_lhs = TYPE_SIZE_UNIT (TREE_TYPE (lhs));
+      tree is_vla_node = gimple_call_arg (stmt, 2);
+      bool is_vla = (bool) TREE_INT_CST_LOW (is_vla_node);
+
+      if (TREE_CODE (lhs) == SSA_NAME)
+       lhs = SSA_NAME_VAR (lhs);
+
+      poly_uint64 size_from_arg0, size_from_lhs;
+      bool is_constant_size_arg0 = poly_int_tree_p (size_of_arg0,
+						    &size_from_arg0);
+      bool is_constant_size_lhs = poly_int_tree_p (size_of_lhs,
+						   &size_from_lhs);
+      if (!is_vla)
+	{
+	  if (!is_constant_size_arg0)
+	    {
+	      error ("%<DEFFERED_INIT%> calls for non-VLA should have "
+		     "constant size for the first argument");
+	      return true;
+	    }
+	  else if (!is_constant_size_lhs)
+	    {
+	      error ("%<DEFFERED_INIT%> calls for non-VLA should have "
+		     "constant size for the LHS");
+	      return true;
+	    }
+	  else if (maybe_ne (size_from_arg0, size_from_lhs))
+	    {
+	      error ("%<DEFFERED_INIT%> calls for non-VLA should have same "
+		     "constant size for the first argument and LHS");
+	      return true;
+	    }
+	}
+    }
+
+  /* We will not verify the arguments for the calls to .DEFERRED_INIT.
+     Such call is not a real call, just a placeholder for a later
+     initialization during expand phase.
+     This is mainly to avoid assertion failure for the following
+     case:
+
+     uni_var = .DEFERRED_INIT (var_size, INIT_TYPE, is_vla);
+     foo (&uni_var);
+
+     in the above, the uninitialized auto variable "uni_var" is
+     addressable, therefore should not be in registers, resulting
+     the assertion failure in the following argument verification.  */
+  if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+    return false;
+
   /* ???  The C frontend passes unpromoted arguments in case it
      didn't see a function declaration before the call.  So for now
      leave the call arguments mostly unverified.  Once we gimplify
      unit-at-a-time we have a chance to fix this.  */
 
-  for (i = 0; i < gimple_call_num_args (stmt); ++i)
-    {
-      tree arg = gimple_call_arg (stmt, i);
-      if ((is_gimple_reg_type (TREE_TYPE (arg))
-	   && !is_gimple_val (arg))
-	  || (!is_gimple_reg_type (TREE_TYPE (arg))
-	      && !is_gimple_lvalue (arg)))
-	{
-	  error ("invalid argument to gimple call");
-	  debug_generic_expr (arg);
-	  return true;
-	}
-      if (!is_gimple_reg (arg))
-	{
-	  if (TREE_CODE (arg) == WITH_SIZE_EXPR)
-	    arg = TREE_OPERAND (arg, 0);
-	  if (verify_types_in_gimple_reference (arg, false))
+  else
+    for (i = 0; i < gimple_call_num_args (stmt); ++i)
+      {
+	tree arg = gimple_call_arg (stmt, i);
+	if ((is_gimple_reg_type (TREE_TYPE (arg))
+	     && !is_gimple_val (arg))
+	    || (!is_gimple_reg_type (TREE_TYPE (arg))
+		&& !is_gimple_lvalue (arg)))
+	  {
+	    error ("invalid argument to gimple call");
+	    debug_generic_expr (arg);
 	    return true;
-	}
-    }
+	  }
+	if (!is_gimple_reg (arg))
+	  {
+	    if (TREE_CODE (arg) == WITH_SIZE_EXPR)
+	      arg = TREE_OPERAND (arg, 0);
+	    if (verify_types_in_gimple_reference (arg, false))
+	      return true;
+	  }
+      }
 
   return false;
 }
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index c05d22f3e8f1..45c9e916f55a 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -384,6 +384,13 @@ static struct
 
   /* Numbber of components created when splitting aggregate parameters.  */
   int param_reductions_created;
+
+  /* Number of deferred_init calls that are modified.  */
+  int deferred_init;
+
+  /* Number of deferred_init calls that are created by
+     generate_subtree_deferred_init.  */
+  int subtree_deferred_init;
 } sra_stats;
 
 static void
@@ -1388,7 +1395,14 @@ scan_function (void)
 
 	      t = gimple_call_lhs (stmt);
 	      if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
-		ret |= build_access_from_expr (t, stmt, true);
+		{
+		  /* If the STMT is a call to DEFERRED_INIT, avoid setting
+		     cannot_scalarize_away_bitmap.  */
+		  if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+		    ret |= !!build_access_from_expr_1 (t, stmt, true);
+		  else
+		    ret |= build_access_from_expr (t, stmt, true);
+		}
 	      break;
 
 	    case GIMPLE_ASM:
@@ -4096,6 +4110,88 @@ get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
   return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
 }
 
+
+/* Generate statements to call .DEFERRED_INIT to initialize scalar replacements
+   of accesses within a subtree ACCESS; all its children, siblings and their
+   children are to be processed.
+   GSI is a statement iterator used to place the new statements.  */
+static void
+generate_subtree_deferred_init (struct access *access,
+				tree init_type,
+				tree is_vla,
+				gimple_stmt_iterator *gsi,
+				location_t loc)
+{
+  do
+    {
+      if (access->grp_to_be_replaced)
+	{
+	  tree repl = get_access_replacement (access);
+	  gimple *call
+	    = gimple_build_call_internal (IFN_DEFERRED_INIT, 3,
+					  TYPE_SIZE_UNIT (TREE_TYPE (repl)),
+					  init_type, is_vla);
+	  gimple_call_set_lhs (call, repl);
+	  gsi_insert_before (gsi, call, GSI_SAME_STMT);
+	  update_stmt (call);
+	  gimple_set_location (call, loc);
+	  sra_stats.subtree_deferred_init++;
+	}
+      if (access->first_child)
+	generate_subtree_deferred_init (access->first_child, init_type,
+					is_vla, gsi, loc);
+
+      access = access ->next_sibling;
+    }
+  while (access);
+}
+
+/* For a call to .DEFERRED_INIT:
+   var = .DEFERRED_INIT (size_of_var, init_type, is_vla);
+   examine the LHS variable VAR and replace it with a scalar replacement if
+   there is one, also replace the RHS call to a call to .DEFERRED_INIT of
+   the corresponding scalar relacement variable.  Examine the subtree and
+   do the scalar replacements in the subtree too.  STMT is the call, GSI is
+   the statment iterator to place newly created statement.  */
+
+static enum assignment_mod_result
+sra_modify_deferred_init (gimple *stmt, gimple_stmt_iterator *gsi)
+{
+  tree lhs = gimple_call_lhs (stmt);
+  tree init_type = gimple_call_arg (stmt, 1);
+  tree is_vla = gimple_call_arg (stmt, 2);
+
+  struct access *lhs_access = get_access_for_expr (lhs);
+  if (!lhs_access)
+    return SRA_AM_NONE;
+
+  location_t loc = gimple_location (stmt);
+
+  if (lhs_access->grp_to_be_replaced)
+    {
+      tree lhs_repl = get_access_replacement (lhs_access);
+      gimple_call_set_lhs (stmt, lhs_repl);
+      tree arg0_repl = TYPE_SIZE_UNIT (TREE_TYPE (lhs_repl));
+      gimple_call_set_arg (stmt, 0, arg0_repl);
+      sra_stats.deferred_init++;
+      gcc_assert (!lhs_access->first_child);
+      return SRA_AM_MODIFIED;
+    }
+
+  if (lhs_access->first_child)
+    generate_subtree_deferred_init (lhs_access->first_child,
+				    init_type, is_vla, gsi, loc);
+  if (lhs_access->grp_covered)
+    {
+      unlink_stmt_vdef (stmt);
+      gsi_remove (gsi, true);
+      release_defs (stmt);
+      return SRA_AM_REMOVED;
+    }
+
+  return SRA_AM_MODIFIED;
+}
+
 /* Examine both sides of the assignment statement pointed to by STMT, replace
    them with a scalare replacement if there is one and generate copying of
    replacements if scalarized aggregates have been used in the assignment.  GSI
@@ -4460,17 +4556,27 @@ sra_modify_function_body (void)
 	      break;
 
 	    case GIMPLE_CALL:
-	      /* Operands must be processed before the lhs.  */
-	      for (i = 0; i < gimple_call_num_args (stmt); i++)
+	      /* Handle calls to .DEFERRED_INIT specially.  */
+	      if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
 		{
-		  t = gimple_call_arg_ptr (stmt, i);
-		  modified |= sra_modify_expr (t, &gsi, false);
+		  assign_result = sra_modify_deferred_init (stmt, &gsi);
+		  modified |= assign_result == SRA_AM_MODIFIED;
+		  deleted = assign_result == SRA_AM_REMOVED;
 		}
-
-	      if (gimple_call_lhs (stmt))
+	      else
 		{
-		  t = gimple_call_lhs_ptr (stmt);
-		  modified |= sra_modify_expr (t, &gsi, true);
+		  /* Operands must be processed before the lhs.  */
+		  for (i = 0; i < gimple_call_num_args (stmt); i++)
+		    {
+		      t = gimple_call_arg_ptr (stmt, i);
+		      modified |= sra_modify_expr (t, &gsi, false);
+		    }
+
+	      	  if (gimple_call_lhs (stmt))
+		    {
+		      t = gimple_call_lhs_ptr (stmt);
+		      modified |= sra_modify_expr (t, &gsi, true);
+		    }
 		}
 	      break;
 
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 71894b38ff92..4e8e0194753d 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -4907,6 +4907,9 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
       && find_func_aliases_for_builtin_call (fn, t))
     return;
 
+  if (gimple_call_internal_p (t, IFN_DEFERRED_INIT))
+    return;
+
   fi = get_fi_for_callee (t);
   if (!in_ipa_mode
       || (fi->decl && fndecl && !fi->is_fn_info))
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 24ac031a693c..445b739bcd88 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -152,6 +152,42 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
   if (is_gimple_assign (context)
       && gimple_assign_rhs_code (context) == COMPLEX_EXPR)
     return;
+
+  /* Ignore REALPART_EXPR or IMAGPART_EXPR if its operand is a call to
+     .DEFERRED_INIT.  This is for handling the following case correctly:
+
+  1 typedef _Complex float C;
+  2 C foo (int cond)
+  3 {
+  4   C f;
+  5   __imag__ f = 0;
+  6   if (cond)
+  7     {
+  8       __real__ f = 1;
+  9       return f;
+ 10     }
+ 11   return f;
+ 12 }
+
+    with -ftrivial-auto-var-init, compiler will insert the following
+    artificial initialization at line 4:
+  f = .DEFERRED_INIT (f, 2);
+  _1 = REALPART_EXPR <f>;
+
+    without the following special handling, _1 = REALPART_EXPR <f> will
+    be treated as the uninitialized use point, which is incorrect. (the
+    real uninitialized use point is at line 11).  */
+  if (is_gimple_assign (context)
+      && (gimple_assign_rhs_code (context) == REALPART_EXPR
+	  || gimple_assign_rhs_code (context) == IMAGPART_EXPR))
+    {
+      tree v = gimple_assign_rhs1 (context);
+      if (TREE_CODE (TREE_OPERAND (v, 0)) == SSA_NAME
+	  && gimple_call_internal_p (SSA_NAME_DEF_STMT (TREE_OPERAND (v, 0)),
+				     IFN_DEFERRED_INIT))
+	return;
+    }
+
   if (!has_undefined_value_p (t))
     return;
 
@@ -227,6 +263,11 @@ check_defs (ao_ref *ref, tree vdef, void *data_)
   check_defs_data *data = (check_defs_data *)data_;
   gimple *def_stmt = SSA_NAME_DEF_STMT (vdef);
 
+  /* Ignore the vdef if the definition statement is a call
+     to .DEFERRED_INIT function.  */
+  if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
+    return false;
+
   /* The ASAN_MARK intrinsic doesn't modify the variable.  */
   if (is_gimple_call (def_stmt)
       && gimple_call_internal_p (def_stmt, IFN_ASAN_MARK))
@@ -642,6 +683,12 @@ warn_uninitialized_vars (bool wmaybe_uninit)
 	  ssa_op_iter op_iter;
 	  tree use;
 
+	  /* The call is an artificial use, will not provide meaningful
+	     error message.  If the result of the call is used somewhere
+	     else, we warn there instead.  */
+	  if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
+	    continue;
+
 	  if (is_gimple_debug (stmt))
 	    continue;
 
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 4cc400d3c2eb..0fba404babe9 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1325,6 +1325,46 @@ ssa_undefined_value_p (tree t, bool partial)
   if (gimple_nop_p (def_stmt))
     return true;
 
+  /* The value is undefined if the definition statement is a call
+     to .DEFERRED_INIT function.  */
+  if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
+    return true;
+
+  /* The value is partially undefined if the definition statement is
+     a REALPART_EXPR or IMAGPART_EXPR and its operand is defined by
+     the call to .DEFERRED_INIT function.  This is for handling the
+     following case:
+
+  1 typedef _Complex float C;
+  2 C foo (int cond)
+  3 {
+  4   C f;
+  5   __imag__ f = 0;
+  6   if (cond)
+  7     {
+  8       __real__ f = 1;
+  9       return f;
+ 10     }
+ 11   return f;
+ 12 }
+
+    with -ftrivial-auto-var-init, compiler will insert the following
+    artificial initialization:
+  f = .DEFERRED_INIT (f, 2);
+  _1 = REALPART_EXPR <f>;
+
+    we should treat the definition _1 = REALPART_EXPR <f> as undefined.  */
+  if (partial && is_gimple_assign (def_stmt)
+      && (gimple_assign_rhs_code (def_stmt) == REALPART_EXPR
+	  || gimple_assign_rhs_code (def_stmt) == IMAGPART_EXPR))
+    {
+      tree real_imag_part = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0);
+      if (TREE_CODE (real_imag_part) == SSA_NAME
+	 && gimple_call_internal_p (SSA_NAME_DEF_STMT (real_imag_part),
+				    IFN_DEFERRED_INIT))
+	return true;
+    }
+
   /* Check if the complex was not only partially defined.  */
   if (partial && is_gimple_assign (def_stmt)
       && gimple_assign_rhs_code (def_stmt) == COMPLEX_EXPR)
-- 
2.27.0


             reply	other threads:[~2021-07-27  3:26 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-27  3:26 Qing Zhao [this message]
2021-07-28 20:21 ` Kees Cook
2021-07-28 21:53   ` Qing Zhao
2021-08-09 14:09 ` Richard Biener
2021-08-09 16:38   ` Qing Zhao
2021-08-09 17:14     ` Richard Biener
2021-08-10  7:36     ` Richard Biener
2021-08-10 13:39       ` Qing Zhao
2021-08-10 14:16         ` Richard Biener
2021-08-10 15:02           ` Qing Zhao
2021-08-10 15:22             ` Richard Biener
2021-08-10 15:55               ` Qing Zhao
2021-08-10 20:16               ` Qing Zhao
2021-08-10 22:26                 ` Qing Zhao
2021-08-11  7:02                   ` Richard Biener
2021-08-11 13:33                     ` Qing Zhao
2021-08-11 13:37                       ` Richard Biener
2021-08-11 13:54                         ` Qing Zhao
2021-08-11 13:58                           ` Richard Biener
2021-08-11 14:00                             ` Qing Zhao
2021-08-11 15:30                             ` Qing Zhao
2021-08-11 15:53                               ` Richard Biener
2021-08-11 16:22                                 ` Qing Zhao
2021-08-11 16:55                                   ` Richard Biener
2021-08-11 16:57                                     ` Qing Zhao
2021-08-11 20:30                                     ` Qing Zhao
2021-08-11 22:03                                       ` Qing Zhao
2021-08-16  7:12                                         ` Richard Biener
2021-08-16 14:48                                           ` Qing Zhao
2021-08-16 15:08                                             ` Richard Biener
2021-08-16 15:39                                               ` Qing Zhao
2021-08-16  7:11                                       ` Richard Biener
2021-08-16 16:48                                         ` Qing Zhao
2021-08-17 15:04                                           ` Qing Zhao
2021-08-17 20:40                                             ` Qing Zhao
2021-08-18  7:19                                               ` Richard Biener
2021-08-18 14:39                                                 ` Qing Zhao
2021-08-11  9:02                   ` Richard Sandiford
2021-08-11 13:44                     ` Qing Zhao
2021-08-11 16:15                       ` Richard Sandiford
2021-08-11 16:29                         ` Qing Zhao
2021-08-12 19:24   ` Qing Zhao
2021-08-12 22:45     ` Qing Zhao
2021-08-16  7:40     ` Richard Biener
2021-08-16 15:45       ` Qing Zhao
2021-08-17  8:29         ` Richard Biener
2021-08-17 14:50           ` Qing Zhao
2021-08-17 16:08             ` Qing Zhao
2021-08-18  7:15               ` Richard Biener
2021-08-18 16:02                 ` Qing Zhao
2021-08-19  9:00                   ` Richard Biener
2021-08-19 13:54                     ` Qing Zhao
2021-08-20 14:52                       ` Qing Zhao
2021-08-23 13:55                       ` Richard Biener
2021-09-02 17:24                         ` Qing Zhao
2021-08-16 19:49       ` Qing Zhao
2021-08-17  8:43         ` Richard Biener
2021-08-17 14:03           ` Qing Zhao
2021-08-17 14:45             ` Richard Biener
2021-08-17 14:53               ` Qing Zhao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52E29277-1403-4755-901A-528116C43FB8@oracle.com \
    --to=qing.zhao@oracle.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=keescook@chromium.org \
    --cc=mjambor@suse.cz \
    --cc=rguenther@suse.de \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).