Update gcc-50 to SVN version 231263 (gcc-5-branch)
authorJohn Marino <draco@marino.st>
Fri, 4 Dec 2015 14:11:37 +0000 (15:11 +0100)
committerJohn Marino <draco@marino.st>
Fri, 4 Dec 2015 15:01:41 +0000 (16:01 +0100)
This is equivalent to the gcc 5.3 release (version shows 5.3.1 though)

Last Changed Date: 2015-12-04 01:16:08 +0100 (Fri, 04 Dec 2015)

184 files changed:
contrib/gcc-5.0/LAST_UPDATED
contrib/gcc-5.0/gcc/BASE-VER
contrib/gcc-5.0/gcc/DATESTAMP
contrib/gcc-5.0/gcc/alias.c
contrib/gcc-5.0/gcc/builtins.c
contrib/gcc-5.0/gcc/c-family/c-common.c
contrib/gcc-5.0/gcc/c-family/c-ubsan.c
contrib/gcc-5.0/gcc/c-family/c.opt
contrib/gcc-5.0/gcc/c/c-decl.c
contrib/gcc-5.0/gcc/c/c-parser.c
contrib/gcc-5.0/gcc/c/c-typeck.c
contrib/gcc-5.0/gcc/calls.c
contrib/gcc-5.0/gcc/cfgexpand.c
contrib/gcc-5.0/gcc/cgraphunit.c
contrib/gcc-5.0/gcc/combine.c
contrib/gcc-5.0/gcc/config/i386/i386.c
contrib/gcc-5.0/gcc/config/i386/i386.h
contrib/gcc-5.0/gcc/config/i386/i386.md
contrib/gcc-5.0/gcc/config/i386/intelmic-mkoffload.c
contrib/gcc-5.0/gcc/config/i386/sse.md
contrib/gcc-5.0/gcc/config/i386/sync.md
contrib/gcc-5.0/gcc/coretypes.h
contrib/gcc-5.0/gcc/cp/call.c
contrib/gcc-5.0/gcc/cp/class.c
contrib/gcc-5.0/gcc/cp/constexpr.c
contrib/gcc-5.0/gcc/cp/cp-tree.h
contrib/gcc-5.0/gcc/cp/cp-ubsan.c
contrib/gcc-5.0/gcc/cp/cvt.c
contrib/gcc-5.0/gcc/cp/decl.c
contrib/gcc-5.0/gcc/cp/decl2.c
contrib/gcc-5.0/gcc/cp/error.c
contrib/gcc-5.0/gcc/cp/init.c
contrib/gcc-5.0/gcc/cp/lambda.c
contrib/gcc-5.0/gcc/cp/mangle.c
contrib/gcc-5.0/gcc/cp/optimize.c
contrib/gcc-5.0/gcc/cp/parser.c
contrib/gcc-5.0/gcc/cp/pt.c
contrib/gcc-5.0/gcc/cp/search.c
contrib/gcc-5.0/gcc/cp/semantics.c
contrib/gcc-5.0/gcc/cp/typeck.c
contrib/gcc-5.0/gcc/df-problems.c
contrib/gcc-5.0/gcc/diagnostic.c
contrib/gcc-5.0/gcc/diagnostic.h
contrib/gcc-5.0/gcc/dojump.c
contrib/gcc-5.0/gcc/dwarf2out.c
contrib/gcc-5.0/gcc/emit-rtl.c
contrib/gcc-5.0/gcc/except.c
contrib/gcc-5.0/gcc/fold-const.c
contrib/gcc-5.0/gcc/function.c
contrib/gcc-5.0/gcc/genmatch.c
contrib/gcc-5.0/gcc/gimple-fold.c
contrib/gcc-5.0/gcc/gimple-low.c
contrib/gcc-5.0/gcc/gimple-ssa-isolate-paths.c
contrib/gcc-5.0/gcc/gimplify.c
contrib/gcc-5.0/gcc/graphite-blocking.c
contrib/gcc-5.0/gcc/graphite-dependences.c
contrib/gcc-5.0/gcc/graphite-interchange.c
contrib/gcc-5.0/gcc/graphite-isl-ast-to-gimple.c
contrib/gcc-5.0/gcc/graphite-optimize-isl.c
contrib/gcc-5.0/gcc/graphite-poly.c
contrib/gcc-5.0/gcc/graphite-poly.h
contrib/gcc-5.0/gcc/graphite-scop-detection.c
contrib/gcc-5.0/gcc/graphite-sese-to-poly.c
contrib/gcc-5.0/gcc/graphite.c
contrib/gcc-5.0/gcc/ifcvt.c
contrib/gcc-5.0/gcc/ipa-chkp.c
contrib/gcc-5.0/gcc/ipa-chkp.h
contrib/gcc-5.0/gcc/ipa-devirt.c
contrib/gcc-5.0/gcc/ipa-icf.c
contrib/gcc-5.0/gcc/ipa-icf.h
contrib/gcc-5.0/gcc/ipa-inline-analysis.c
contrib/gcc-5.0/gcc/ipa-polymorphic-call.c
contrib/gcc-5.0/gcc/ipa-prop.c
contrib/gcc-5.0/gcc/ipa-prop.h
contrib/gcc-5.0/gcc/ira-color.c
contrib/gcc-5.0/gcc/ira-int.h
contrib/gcc-5.0/gcc/ira-lives.c
contrib/gcc-5.0/gcc/ira.c
contrib/gcc-5.0/gcc/ira.h
contrib/gcc-5.0/gcc/lra-constraints.c
contrib/gcc-5.0/gcc/lra-int.h
contrib/gcc-5.0/gcc/lra-lives.c
contrib/gcc-5.0/gcc/lra-remat.c
contrib/gcc-5.0/gcc/lra.c
contrib/gcc-5.0/gcc/lto-cgraph.c
contrib/gcc-5.0/gcc/omp-low.c
contrib/gcc-5.0/gcc/optabs.c
contrib/gcc-5.0/gcc/ree.c
contrib/gcc-5.0/gcc/rtl.h
contrib/gcc-5.0/gcc/sched-deps.c
contrib/gcc-5.0/gcc/sel-sched.c
contrib/gcc-5.0/gcc/stor-layout.c
contrib/gcc-5.0/gcc/target-globals.c
contrib/gcc-5.0/gcc/tree-chkp.c
contrib/gcc-5.0/gcc/tree-chkp.h
contrib/gcc-5.0/gcc/tree-if-conv.c
contrib/gcc-5.0/gcc/tree-inline.c
contrib/gcc-5.0/gcc/tree-sra.c
contrib/gcc-5.0/gcc/tree-ssa-alias.c
contrib/gcc-5.0/gcc/tree-ssa-ccp.c
contrib/gcc-5.0/gcc/tree-ssa-dce.c
contrib/gcc-5.0/gcc/tree-ssa-ifcombine.c
contrib/gcc-5.0/gcc/tree-ssa-live.c
contrib/gcc-5.0/gcc/tree-ssa-loop-im.c
contrib/gcc-5.0/gcc/tree-ssa-math-opts.c
contrib/gcc-5.0/gcc/tree-ssa-phiopt.c
contrib/gcc-5.0/gcc/tree-ssa-reassoc.c
contrib/gcc-5.0/gcc/tree-ssa-sccvn.c
contrib/gcc-5.0/gcc/tree-ssa-structalias.c
contrib/gcc-5.0/gcc/tree-ssa-tail-merge.c
contrib/gcc-5.0/gcc/tree-ssa-uninit.c
contrib/gcc-5.0/gcc/tree-ssanames.c
contrib/gcc-5.0/gcc/tree-ssanames.h
contrib/gcc-5.0/gcc/tree-tailcall.c
contrib/gcc-5.0/gcc/tree-vect-data-refs.c
contrib/gcc-5.0/gcc/tree-vect-generic.c
contrib/gcc-5.0/gcc/tree-vect-loop.c
contrib/gcc-5.0/gcc/tree-vect-stmts.c
contrib/gcc-5.0/gcc/tree-vectorizer.h
contrib/gcc-5.0/gcc/tree.c
contrib/gcc-5.0/gcc/tree.h
contrib/gcc-5.0/gcc/tsan.c
contrib/gcc-5.0/gcc/varasm.c
contrib/gcc-5.0/gcc/wide-int.cc
contrib/gcc-5.0/gcc/wide-int.h
contrib/gcc-5.0/libcpp/errors.c
contrib/gcc-5.0/libcpp/files.c
contrib/gcc-5.0/libcpp/include/cpplib.h
contrib/gcc-5.0/libgcc/config.host
contrib/gcc-5.0/libgcc/config/aarch64/crtfastmath.c [deleted file]
contrib/gcc-5.0/libgcc/config/aarch64/crti.S [deleted file]
contrib/gcc-5.0/libgcc/config/aarch64/crtn.S [deleted file]
contrib/gcc-5.0/libgcc/config/aarch64/linux-unwind.h [deleted file]
contrib/gcc-5.0/libgcc/config/aarch64/sfp-exceptions.c [deleted file]
contrib/gcc-5.0/libgcc/config/aarch64/sfp-machine.h [deleted file]
contrib/gcc-5.0/libgcc/config/aarch64/sync-cache.c [deleted file]
contrib/gcc-5.0/libgcc/config/aarch64/t-aarch64 [deleted file]
contrib/gcc-5.0/libgcc/config/aarch64/t-softfp [deleted file]
contrib/gcc-5.0/libgcc/config/gmon-sol2.c [deleted file]
contrib/gcc-5.0/libgcc/config/i386/cpuinfo.c
contrib/gcc-5.0/libgcc/config/nios2/linux-atomic.c
contrib/gcc-5.0/libgomp/iter.c
contrib/gcc-5.0/libgomp/iter_ull.c
contrib/gcc-5.0/libgomp/oacc-host.c
contrib/gcc-5.0/libgomp/oacc-init.c
contrib/gcc-5.0/libgomp/oacc-int.h
contrib/gcc-5.0/libstdc++-v3/config/cpu/aarch64/atomic_word.h [new file with mode: 0644]
contrib/gcc-5.0/libstdc++-v3/config/locale/generic/c_locale.h [deleted file]
contrib/gcc-5.0/libstdc++-v3/config/locale/generic/codecvt_members.cc [deleted file]
contrib/gcc-5.0/libstdc++-v3/config/locale/generic/collate_members.cc [deleted file]
contrib/gcc-5.0/libstdc++-v3/config/locale/generic/monetary_members.cc [deleted file]
contrib/gcc-5.0/libstdc++-v3/config/locale/generic/numeric_members.cc [deleted file]
contrib/gcc-5.0/libstdc++-v3/config/locale/generic/time_members.cc [deleted file]
contrib/gcc-5.0/libstdc++-v3/config/locale/generic/time_members.h [deleted file]
contrib/gcc-5.0/libstdc++-v3/include/bits/allocator.h
contrib/gcc-5.0/libstdc++-v3/include/bits/atomic_base.h
contrib/gcc-5.0/libstdc++-v3/include/bits/atomic_futex.h
contrib/gcc-5.0/libstdc++-v3/include/bits/basic_string.h
contrib/gcc-5.0/libstdc++-v3/include/bits/char_traits.h
contrib/gcc-5.0/libstdc++-v3/include/bits/ios_base.h
contrib/gcc-5.0/libstdc++-v3/include/bits/locale_conv.h
contrib/gcc-5.0/libstdc++-v3/include/bits/quoted_string.h [new file with mode: 0644]
contrib/gcc-5.0/libstdc++-v3/include/bits/range_access.h
contrib/gcc-5.0/libstdc++-v3/include/bits/regex_compiler.h
contrib/gcc-5.0/libstdc++-v3/include/bits/regex_compiler.tcc
contrib/gcc-5.0/libstdc++-v3/include/bits/regex_scanner.tcc
contrib/gcc-5.0/libstdc++-v3/include/bits/stl_deque.h
contrib/gcc-5.0/libstdc++-v3/include/bits/stl_multiset.h
contrib/gcc-5.0/libstdc++-v3/include/bits/stl_set.h
contrib/gcc-5.0/libstdc++-v3/include/c_global/cmath
contrib/gcc-5.0/libstdc++-v3/include/experimental/filesystem [new file with mode: 0644]
contrib/gcc-5.0/libstdc++-v3/include/experimental/fs_dir.h [new file with mode: 0644]
contrib/gcc-5.0/libstdc++-v3/include/experimental/fs_fwd.h [new file with mode: 0644]
contrib/gcc-5.0/libstdc++-v3/include/experimental/fs_ops.h [new file with mode: 0644]
contrib/gcc-5.0/libstdc++-v3/include/experimental/fs_path.h [new file with mode: 0644]
contrib/gcc-5.0/libstdc++-v3/include/experimental/functional
contrib/gcc-5.0/libstdc++-v3/include/ext/pod_char_traits.h
contrib/gcc-5.0/libstdc++-v3/include/std/atomic
contrib/gcc-5.0/libstdc++-v3/include/std/iomanip
contrib/gcc-5.0/libstdc++-v3/include/std/shared_mutex
contrib/gcc-5.0/libstdc++-v3/include/tr1/cmath
contrib/gcc-5.0/libstdc++-v3/libsupc++/eh_ptr.cc
contrib/gcc-5.0/libstdc++-v3/src/c++11/codecvt.cc
contrib/gcc-5.0/libstdc++-v3/src/c++11/random.cc

index e47392f..fceaaa2 100644 (file)
@@ -1,2 +1,2 @@
-225979
-Last Changed Date: 2015-07-18 02:16:08 +0200 (Sat, 18 Jul 2015)
+231244:231263
+Last Changed Date: 2015-12-04 01:16:08 +0100 (Fri, 04 Dec 2015)
index a7160f3..d85830e 100644 (file)
@@ -364,15 +364,16 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
       || !MEM_SIZE_KNOWN_P (mem))
     return true;
 
-  /* If the base decl is a parameter we can have negative MEM_OFFSET in
-     case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
-     here.  */
+  /* If MEM_OFFSET/MEM_SIZE get us outside of ref->offset/ref->max_size
+     drop ref->ref.  */
   if (MEM_OFFSET (mem) < 0
-      && (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size)
-    return true;
+      || (ref->max_size != -1
+         && ((MEM_OFFSET (mem) + MEM_SIZE (mem)) * BITS_PER_UNIT
+             > ref->max_size)))
+    ref->ref = NULL_TREE;
 
-  /* Otherwise continue and refine size and offset we got from analyzing
-     MEM_EXPR by using MEM_SIZE and MEM_OFFSET.  */
+  /* Refine size and offset we got from analyzing MEM_EXPR by using
+     MEM_SIZE and MEM_OFFSET.  */
 
   ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT;
   ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
index bcbc11d..1370015 100644 (file)
@@ -5271,7 +5271,7 @@ expand_builtin_sync_operation (machine_mode mode, tree exp,
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
 
-  return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SEQ_CST,
+  return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
                                 after);
 }
 
@@ -5301,8 +5301,8 @@ expand_builtin_compare_and_swap (machine_mode mode, tree exp,
        poval = &target;
     }
   if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
-                                      false, MEMMODEL_SEQ_CST,
-                                      MEMMODEL_SEQ_CST))
+                                      false, MEMMODEL_SYNC_SEQ_CST,
+                                      MEMMODEL_SYNC_SEQ_CST))
     return NULL_RTX;
 
   return target;
@@ -5337,7 +5337,7 @@ expand_builtin_sync_lock_release (machine_mode mode, tree exp)
   /* Expand the operands.  */
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
 
-  expand_atomic_store (mem, const0_rtx, MEMMODEL_RELEASE, true);
+  expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
 }
 
 /* Given an integer representing an ``enum memmodel'', verify its
@@ -5366,7 +5366,8 @@ get_memmodel (tree exp)
       return MEMMODEL_SEQ_CST;
     }
 
-  if ((INTVAL (op) & MEMMODEL_MASK) >= MEMMODEL_LAST)
+  /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
+  if (memmodel_base (val) >= MEMMODEL_LAST)
     {
       warning (OPT_Winvalid_memory_model,
               "invalid memory model argument to builtin");
@@ -5433,8 +5434,7 @@ expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp,
       success = MEMMODEL_SEQ_CST;
     }
  
-  if ((failure & MEMMODEL_MASK) == MEMMODEL_RELEASE
-      || (failure & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_release (failure) || is_mm_acq_rel (failure))
     {
       warning (OPT_Winvalid_memory_model,
               "invalid failure memory model for "
@@ -5496,8 +5496,7 @@ expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
   enum memmodel model;
 
   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
-  if ((model & MEMMODEL_MASK) == MEMMODEL_RELEASE
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_release (model) || is_mm_acq_rel (model))
     {
       warning (OPT_Winvalid_memory_model,
               "invalid memory model for %<__atomic_load%>");
@@ -5526,9 +5525,8 @@ expand_builtin_atomic_store (machine_mode mode, tree exp)
   enum memmodel model;
 
   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
-  if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED
-      && (model & MEMMODEL_MASK) != MEMMODEL_SEQ_CST
-      && (model & MEMMODEL_MASK) != MEMMODEL_RELEASE)
+  if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
+       || is_mm_release (model)))
     {
       warning (OPT_Winvalid_memory_model,
               "invalid memory model for %<__atomic_store%>");
@@ -5635,9 +5633,7 @@ expand_builtin_atomic_clear (tree exp)
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
 
-  if ((model & MEMMODEL_MASK) == MEMMODEL_CONSUME
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQUIRE
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
     {
       warning (OPT_Winvalid_memory_model,
               "invalid memory model for %<__atomic_store%>");
@@ -5697,8 +5693,20 @@ fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
   mode = mode_for_size (size, MODE_INT, 0);
   mode_align = GET_MODE_ALIGNMENT (mode);
 
-  if (TREE_CODE (arg1) == INTEGER_CST && INTVAL (expand_normal (arg1)) == 0)
-    type_align = mode_align;
+  if (TREE_CODE (arg1) == INTEGER_CST)
+    {
+      unsigned HOST_WIDE_INT val = UINTVAL (expand_normal (arg1));
+
+      /* Either this argument is null, or it's a fake pointer encoding
+         the alignment of the object.  */
+      val = val & -val;
+      val *= BITS_PER_UNIT;
+
+      if (val == 0 || mode_align < val)
+        type_align = mode_align;
+      else
+        type_align = val;
+    }
   else
     {
       tree ttype = TREE_TYPE (arg1);
@@ -5833,7 +5841,7 @@ expand_builtin_atomic_signal_fence (tree exp)
 static void
 expand_builtin_sync_synchronize (void)
 {
-  expand_mem_thread_fence (MEMMODEL_SEQ_CST);
+  expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
 }
 
 static rtx
index 7fe7fa6..117f89c 100644 (file)
@@ -10741,7 +10741,7 @@ get_atomic_generic_size (location_t loc, tree function,
       if (TREE_CODE (p) == INTEGER_CST)
         {
          int i = tree_to_uhwi (p);
-         if (i < 0 || (i & MEMMODEL_MASK) >= MEMMODEL_LAST)
+         if (i < 0 || (memmodel_base (i) >= MEMMODEL_LAST))
            {
              warning_at (loc, OPT_Winvalid_memory_model,
                          "invalid memory model argument %d of %qE", x + 1,
index a14426f..44f8964 100644 (file)
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "internal-fn.h"
 #include "stor-layout.h"
 #include "builtins.h"
+#include "gimplify.h"
 
 /* Instrument division by zero and INT_MIN / -1.  If not instrumenting,
    return NULL_TREE.  */
@@ -71,6 +72,9 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
   gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0))
              == TYPE_MAIN_VARIANT (TREE_TYPE (op1)));
 
+  op0 = unshare_expr (op0);
+  op1 = unshare_expr (op1);
+
   if (TREE_CODE (type) == INTEGER_TYPE
       && (flag_sanitize & SANITIZE_DIVIDE))
     t = fold_build2 (EQ_EXPR, boolean_type_node,
@@ -117,6 +121,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
        }
     }
   t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
+  t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op1, t);
   if (flag_sanitize_undefined_trap_on_error)
     tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
   else
@@ -151,6 +156,9 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
   HOST_WIDE_INT op0_prec = TYPE_PRECISION (type0);
   tree uprecm1 = build_int_cst (op1_utype, op0_prec - 1);
 
+  op0 = unshare_expr (op0);
+  op1 = unshare_expr (op1);
+
   t = fold_convert_loc (loc, op1_utype, op1);
   t = fold_build2 (GT_EXPR, boolean_type_node, t, uprecm1);
 
index 983f4a8..4162566 100644 (file)
@@ -1592,7 +1592,7 @@ C++ ObjC++ Alias(std=c++1z) Undocumented
 
 std=c11
 C ObjC
-Conform to the ISO 2011 C standard (experimental and incomplete support)
+Conform to the ISO 2011 C standard
 
 std=c1x
 C ObjC Alias(std=c11)
@@ -1648,7 +1648,7 @@ C++ ObjC++ Alias(std=gnu++1z) Undocumented
 
 std=gnu11
 C ObjC
-Conform to the ISO 2011 C standard with GNU extensions (experimental and incomplete support)
+Conform to the ISO 2011 C standard with GNU extensions
 
 std=gnu1x
 C ObjC Alias(std=gnu11)
@@ -1688,7 +1688,7 @@ Deprecated in favor of -std=iso9899:1999
 
 std=iso9899:2011
 C ObjC Alias(std=c11)
-Conform to the ISO 2011 C standard (experimental and incomplete support)
+Conform to the ISO 2011 C standard
 
 traditional
 Driver
index 03ce316..ad704bf 100644 (file)
@@ -8883,7 +8883,8 @@ temp_pop_parm_decls (void)
   current_scope->bindings = NULL;
   for (; b; b = free_binding_and_advance (b))
     {
-      gcc_assert (TREE_CODE (b->decl) == PARM_DECL);
+      gcc_assert (TREE_CODE (b->decl) == PARM_DECL
+                 || b->decl == error_mark_node);
       gcc_assert (I_SYMBOL_BINDING (b->id) == b);
       I_SYMBOL_BINDING (b->id) = b->shadowed;
       if (b->shadowed && b->shadowed->u.type)
index 007cb8a..86cbc40 100644 (file)
@@ -11185,9 +11185,9 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list)
       tree alignment = c_parser_expr_no_commas (parser, NULL).value;
       mark_exp_read (alignment);
       alignment = c_fully_fold (alignment, false, NULL);
-      if (!INTEGRAL_TYPE_P (TREE_TYPE (alignment))
-         && TREE_CODE (alignment) != INTEGER_CST
-         && tree_int_cst_sgn (alignment) != 1)
+      if (TREE_CODE (alignment) != INTEGER_CST
+         || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
+         || tree_int_cst_sgn (alignment) != 1)
        {
          error_at (clause_loc, "%<aligned%> clause alignment expression must "
                                "be positive constant integer expression");
@@ -11264,9 +11264,9 @@ c_parser_omp_clause_safelen (c_parser *parser, tree list)
   t = c_parser_expr_no_commas (parser, NULL).value;
   mark_exp_read (t);
   t = c_fully_fold (t, false, NULL);
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
-      && TREE_CODE (t) != INTEGER_CST
-      && tree_int_cst_sgn (t) != 1)
+  if (TREE_CODE (t) != INTEGER_CST
+      || !INTEGRAL_TYPE_P (TREE_TYPE (t))
+      || tree_int_cst_sgn (t) != 1)
     {
       error_at (clause_loc, "%<safelen%> clause expression must "
                            "be positive constant integer expression");
@@ -11300,9 +11300,9 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list)
   t = c_parser_expr_no_commas (parser, NULL).value;
   mark_exp_read (t);
   t = c_fully_fold (t, false, NULL);
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
-      && TREE_CODE (t) != INTEGER_CST
-      && tree_int_cst_sgn (t) != 1)
+  if (TREE_CODE (t) != INTEGER_CST
+      || !INTEGRAL_TYPE_P (TREE_TYPE (t))
+      || tree_int_cst_sgn (t) != 1)
     {
       error_at (clause_loc, "%<simdlen%> clause expression must "
                            "be positive constant integer expression");
@@ -11706,7 +11706,7 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
 
       first = false;
 
-      if (((mask >> c_kind) & 1) == 0 && !parser->error)
+      if (((mask >> c_kind) & 1) == 0)
        {
          /* Remove the invalid clause(s) from the list to avoid
             confusing the rest of the compiler.  */
@@ -11935,7 +11935,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
 
       first = false;
 
-      if (((mask >> c_kind) & 1) == 0 && !parser->error)
+      if (((mask >> c_kind) & 1) == 0)
        {
          /* Remove the invalid clause(s) from the list to avoid
             confusing the rest of the compiler.  */
@@ -12379,6 +12379,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
   bool structured_block = false;
   bool swapped = false;
   bool seq_cst = false;
+  bool non_lvalue_p;
 
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
@@ -12432,20 +12433,33 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
     {
     case OMP_ATOMIC_READ:
     case NOP_EXPR: /* atomic write */
-      v = c_parser_unary_expression (parser).value;
+      v = c_parser_cast_expression (parser, NULL).value;
+      non_lvalue_p = !lvalue_p (v);
       v = c_fully_fold (v, false, NULL);
       if (v == error_mark_node)
        goto saw_error;
+      if (non_lvalue_p)
+       v = non_lvalue (v);
       loc = c_parser_peek_token (parser)->location;
       if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
        goto saw_error;
       if (code == NOP_EXPR)
-       lhs = c_parser_expression (parser).value;
+       {
+         lhs = c_parser_expression (parser).value;
+         lhs = c_fully_fold (lhs, false, NULL);
+         if (lhs == error_mark_node)
+           goto saw_error;
+       }
       else
-       lhs = c_parser_unary_expression (parser).value;
-      lhs = c_fully_fold (lhs, false, NULL);
-      if (lhs == error_mark_node)
-       goto saw_error;
+       {
+         lhs = c_parser_cast_expression (parser, NULL).value;
+         non_lvalue_p = !lvalue_p (lhs);
+         lhs = c_fully_fold (lhs, false, NULL);
+         if (lhs == error_mark_node)
+           goto saw_error;
+         if (non_lvalue_p)
+           lhs = non_lvalue (lhs);
+       }
       if (code == NOP_EXPR)
        {
          /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
@@ -12464,10 +12478,13 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
        }
       else
        {
-         v = c_parser_unary_expression (parser).value;
+         v = c_parser_cast_expression (parser, NULL).value;
+         non_lvalue_p = !lvalue_p (v);
          v = c_fully_fold (v, false, NULL);
          if (v == error_mark_node)
            goto saw_error;
+         if (non_lvalue_p)
+           v = non_lvalue (v);
          if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
            goto saw_error;
        }
@@ -12480,7 +12497,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
      old or new x should be captured.  */
 restart:
   eloc = c_parser_peek_token (parser)->location;
-  expr = c_parser_unary_expression (parser);
+  expr = c_parser_cast_expression (parser, NULL);
   lhs = expr.value;
   expr = default_function_array_conversion (eloc, expr);
   unfolded_lhs = expr.value;
@@ -12573,6 +12590,8 @@ restart:
        }
       /* FALLTHRU */
     default:
+      if (!lvalue_p (unfolded_lhs))
+       lhs = non_lvalue (lhs);
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_MULT_EQ:
@@ -12687,20 +12706,25 @@ stmt_done:
     {
       if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
        goto saw_error;
-      v = c_parser_unary_expression (parser).value;
+      v = c_parser_cast_expression (parser, NULL).value;
+      non_lvalue_p = !lvalue_p (v);
       v = c_fully_fold (v, false, NULL);
       if (v == error_mark_node)
        goto saw_error;
+      if (non_lvalue_p)
+       v = non_lvalue (v);
       if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
        goto saw_error;
       eloc = c_parser_peek_token (parser)->location;
-      expr = c_parser_unary_expression (parser);
+      expr = c_parser_cast_expression (parser, NULL);
       lhs1 = expr.value;
       expr = default_function_array_read_conversion (eloc, expr);
       unfolded_lhs1 = expr.value;
       lhs1 = c_fully_fold (lhs1, false, NULL);
       if (lhs1 == error_mark_node)
        goto saw_error;
+      if (!lvalue_p (unfolded_lhs1))
+       lhs1 = non_lvalue (lhs1);
     }
   if (structured_block)
     {
@@ -12802,7 +12826,8 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
                       tree clauses, tree *cclauses)
 {
   tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
-  tree declv, condv, incrv, initv, ret = NULL;
+  tree declv, condv, incrv, initv, ret = NULL_TREE;
+  tree pre_body = NULL_TREE, this_pre_body;
   bool fail = false, open_brace_parsed = false;
   int i, collapse = 1, nbraces = 0;
   location_t for_loc;
@@ -12846,8 +12871,23 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
        {
          if (i > 0)
            vec_safe_push (for_block, c_begin_compound_stmt (true));
+         this_pre_body = push_stmt_list ();
          c_parser_declaration_or_fndef (parser, true, true, true, true, true,
                                         NULL, vNULL);
+         if (this_pre_body)
+           {
+             this_pre_body = pop_stmt_list (this_pre_body);
+             if (pre_body)
+               {
+                 tree t = pre_body;   
+                 pre_body = push_stmt_list ();
+                 add_stmt (t);
+                 add_stmt (this_pre_body);
+                 pre_body = pop_stmt_list (pre_body);
+               }
+             else
+               pre_body = this_pre_body;
+           }
          decl = check_for_loop_decls (for_loc, flag_isoc99);
          if (decl == NULL)
            goto error_init;
@@ -13042,7 +13082,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
   if (!fail)
     {
       stmt = c_finish_omp_for (loc, code, declv, initv, condv,
-                              incrv, body, NULL);
+                              incrv, body, pre_body);
       if (stmt)
        {
          if (cclauses != NULL
index ebe4c73..ffba66b 100644 (file)
@@ -5707,6 +5707,10 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
   tree rname = NULL_TREE;
   bool objc_ok = false;
 
+  /* Use the expansion point location to handle cases such as user's
+     function returning a wrong-type macro defined in a system header.  */
+  location = expansion_point_location_if_in_system_header (location);
+
   if (errtype == ic_argpass)
     {
       tree selector;
@@ -9368,8 +9372,12 @@ c_finish_return (location_t loc, tree retval, tree origtype)
   bool npc = false;
   size_t rank = 0;
 
+  /* Use the expansion point to handle cases such as returning NULL
+     in a function returning void.  */
+  source_location xloc = expansion_point_location_if_in_system_header (loc);
+
   if (TREE_THIS_VOLATILE (current_function_decl))
-    warning_at (loc, 0,
+    warning_at (xloc, 0,
                "function declared %<noreturn%> has a %<return%> statement");
 
   if (flag_cilkplus && contains_array_notation_expr (retval))
@@ -9424,10 +9432,10 @@ c_finish_return (location_t loc, tree retval, tree origtype)
     {
       current_function_returns_null = 1;
       if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
-       pedwarn (loc, 0,
+       pedwarn (xloc, 0,
                 "%<return%> with a value, in function returning void");
       else
-       pedwarn (loc, OPT_Wpedantic, "ISO C forbids "
+       pedwarn (xloc, OPT_Wpedantic, "ISO C forbids "
                 "%<return%> with expression, in function returning void");
     }
   else
index 32ea4eb..ee8ea5f 100644 (file)
@@ -3115,6 +3115,19 @@ expand_call (tree exp, rtx target, int ignore)
 
       compute_argument_addresses (args, argblock, num_actuals);
 
+      /* Stack is properly aligned, pops can't safely be deferred during
+        the evaluation of the arguments.  */
+      NO_DEFER_POP;
+
+      /* Precompute all register parameters.  It isn't safe to compute
+        anything once we have started filling any specific hard regs.
+        TLS symbols sometimes need a call to resolve.  Precompute
+        register parameters before any stack pointer manipulation
+        to avoid unaligned stack in the called function.  */
+      precompute_register_parameters (num_actuals, args, &reg_parm_seen);
+
+      OK_DEFER_POP;
+
       /* Perform stack alignment before the first push (the last arg).  */
       if (argblock == 0
           && adjusted_args_size.constant > reg_parm_stack_space
@@ -3155,10 +3168,6 @@ expand_call (tree exp, rtx target, int ignore)
 
       funexp = rtx_for_function_call (fndecl, addr);
 
-      /* Precompute all register parameters.  It isn't safe to compute anything
-        once we have started filling any specific hard regs.  */
-      precompute_register_parameters (num_actuals, args, &reg_parm_seen);
-
       if (CALL_EXPR_STATIC_CHAIN (exp))
        static_chain_value = expand_normal (CALL_EXPR_STATIC_CHAIN (exp));
       else
@@ -4950,6 +4959,13 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
              if (XEXP (x, 0) != crtl->args.internal_arg_pointer)
                i = INTVAL (XEXP (XEXP (x, 0), 1));
 
+             /* arg.locate doesn't contain the pretend_args_size offset,
+                it's part of argblock.  Ensure we don't count it in I.  */
+#ifdef STACK_GROWS_DOWNWARD
+               i -= crtl->args.pretend_args_size;
+#else
+               i += crtl->args.pretend_args_size;
+#endif
              /* expand_call should ensure this.  */
              gcc_assert (!arg->locate.offset.var
                          && arg->locate.size.var == 0
index 97e7a25..3293ea6 100644 (file)
@@ -3219,18 +3219,25 @@ expand_return (tree retval, tree bounds)
   bounds_rtl = DECL_BOUNDS_RTL (DECL_RESULT (current_function_decl));
   if (bounds_rtl)
     {
-      rtx addr, bnd;
+      rtx addr = NULL;
+      rtx bnd = NULL;
 
-      if (bounds)
+      if (bounds && bounds != error_mark_node)
        {
          bnd = expand_normal (bounds);
          targetm.calls.store_returned_bounds (bounds_rtl, bnd);
        }
       else if (REG_P (bounds_rtl))
        {
-         addr = expand_normal (build_fold_addr_expr (retval_rhs));
-         addr = gen_rtx_MEM (Pmode, addr);
-         bnd = targetm.calls.load_bounds_for_arg (addr, NULL, NULL);
+         if (bounds)
+           bnd = chkp_expand_zero_bounds ();
+         else
+           {
+             addr = expand_normal (build_fold_addr_expr (retval_rhs));
+             addr = gen_rtx_MEM (Pmode, addr);
+             bnd = targetm.calls.load_bounds_for_arg (addr, NULL, NULL);
+           }
+
          targetm.calls.store_returned_bounds (bounds_rtl, bnd);
        }
       else
@@ -3239,15 +3246,23 @@ expand_return (tree retval, tree bounds)
 
          gcc_assert (GET_CODE (bounds_rtl) == PARALLEL);
 
-         addr = expand_normal (build_fold_addr_expr (retval_rhs));
-         addr = gen_rtx_MEM (Pmode, addr);
+         if (bounds)
+           bnd = chkp_expand_zero_bounds ();
+         else
+           {
+             addr = expand_normal (build_fold_addr_expr (retval_rhs));
+             addr = gen_rtx_MEM (Pmode, addr);
+           }
 
          for (n = 0; n < XVECLEN (bounds_rtl, 0); n++)
            {
-             rtx offs = XEXP (XVECEXP (bounds_rtl, 0, n), 1);
              rtx slot = XEXP (XVECEXP (bounds_rtl, 0, n), 0);
-             rtx from = adjust_address (addr, Pmode, INTVAL (offs));
-             rtx bnd = targetm.calls.load_bounds_for_arg (from, NULL, NULL);
+             if (!bounds)
+               {
+                 rtx offs = XEXP (XVECEXP (bounds_rtl, 0, n), 1);
+                 rtx from = adjust_address (addr, Pmode, INTVAL (offs));
+                 bnd = targetm.calls.load_bounds_for_arg (from, NULL, NULL);
+               }
              targetm.calls.store_returned_bounds (slot, bnd);
            }
        }
@@ -3344,33 +3359,40 @@ expand_gimple_stmt_1 (gimple stmt)
       break;
 
     case GIMPLE_RETURN:
-      op0 = gimple_return_retval (as_a <greturn *> (stmt));
+      {
+       tree bnd = gimple_return_retbnd (as_a <greturn *> (stmt));
+       op0 = gimple_return_retval (as_a <greturn *> (stmt));
 
-      if (op0 && op0 != error_mark_node)
-       {
-         tree result = DECL_RESULT (current_function_decl);
+       if (op0 && op0 != error_mark_node)
+         {
+           tree result = DECL_RESULT (current_function_decl);
 
-         /* If we are not returning the current function's RESULT_DECL,
-            build an assignment to it.  */
-         if (op0 != result)
-           {
-             /* I believe that a function's RESULT_DECL is unique.  */
-             gcc_assert (TREE_CODE (op0) != RESULT_DECL);
-
-             /* ??? We'd like to use simply expand_assignment here,
-                but this fails if the value is of BLKmode but the return
-                decl is a register.  expand_return has special handling
-                for this combination, which eventually should move
-                to common code.  See comments there.  Until then, let's
-                build a modify expression :-/  */
-             op0 = build2 (MODIFY_EXPR, TREE_TYPE (result),
-                           result, op0);
-           }
-       }
-      if (!op0)
-       expand_null_return ();
-      else
-       expand_return (op0, gimple_return_retbnd (stmt));
+           /* If we are not returning the current function's RESULT_DECL,
+              build an assignment to it.  */
+           if (op0 != result)
+             {
+               /* I believe that a function's RESULT_DECL is unique.  */
+               gcc_assert (TREE_CODE (op0) != RESULT_DECL);
+
+               /* ??? We'd like to use simply expand_assignment here,
+                  but this fails if the value is of BLKmode but the return
+                  decl is a register.  expand_return has special handling
+                  for this combination, which eventually should move
+                  to common code.  See comments there.  Until then, let's
+                  build a modify expression :-/  */
+               op0 = build2 (MODIFY_EXPR, TREE_TYPE (result),
+                             result, op0);
+             }
+           /* Mark we have return statement with missing bounds.  */
+           if (!bnd && chkp_function_instrumented_p (cfun->decl))
+             bnd = error_mark_node;
+         }
+
+       if (!op0)
+         expand_null_return ();
+       else
+         expand_return (op0, bnd);
+      }
       break;
 
     case GIMPLE_ASSIGN:
index 2315ba8..78b2b59 100644 (file)
@@ -2505,6 +2505,7 @@ cgraph_node::create_wrapper (cgraph_node *target)
   memset (&thunk, 0, sizeof (cgraph_thunk_info));
   thunk.thunk_p = true;
   create_edge (target, NULL, count, CGRAPH_FREQ_BASE);
+  callees->can_throw_external = !TREE_NOTHROW (target->decl);
 
   tree arguments = DECL_ARGUMENTS (decl);
 
index 46cd6db..ea47b32 100644 (file)
@@ -11432,8 +11432,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
                 tmode != GET_MODE (op0); tmode = GET_MODE_WIDER_MODE (tmode))
              if ((unsigned HOST_WIDE_INT) c0 == GET_MODE_MASK (tmode))
                {
-                 op0 = gen_lowpart (tmode, inner_op0);
-                 op1 = gen_lowpart (tmode, inner_op1);
+                 op0 = gen_lowpart_or_truncate (tmode, inner_op0);
+                 op1 = gen_lowpart_or_truncate (tmode, inner_op1);
                  code = unsigned_condition (code);
                  changed = 1;
                  break;
@@ -11951,23 +11951,21 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
                                   & GET_MODE_MASK (mode))
                                  + 1)) >= 0
              && const_op >> i == 0
-             && (tmode = mode_for_size (i, MODE_INT, 1)) != BLKmode
-             && (TRULY_NOOP_TRUNCATION_MODES_P (tmode, GET_MODE (op0))
-                 || (REG_P (XEXP (op0, 0))
-                     && reg_truncated_to_mode (tmode, XEXP (op0, 0)))))
+             && (tmode = mode_for_size (i, MODE_INT, 1)) != BLKmode)
            {
-             op0 = gen_lowpart (tmode, XEXP (op0, 0));
+             op0 = gen_lowpart_or_truncate (tmode, XEXP (op0, 0));
              continue;
            }
 
-         /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1
+         /* If this is (and:M1 (subreg:M1 X:M2 0) (const_int C1)) where C1
             fits in both M1 and M2 and the SUBREG is either paradoxical
             or represents the low part, permute the SUBREG and the AND
             and try again.  */
-         if (GET_CODE (XEXP (op0, 0)) == SUBREG)
+         if (GET_CODE (XEXP (op0, 0)) == SUBREG
+             && CONST_INT_P (XEXP (op0, 1)))
            {
-             unsigned HOST_WIDE_INT c1;
              tmode = GET_MODE (SUBREG_REG (XEXP (op0, 0)));
+             unsigned HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1));
              /* Require an integral mode, to avoid creating something like
                 (AND:SF ...).  */
              if (SCALAR_INT_MODE_P (tmode)
@@ -11977,18 +11975,22 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
                     have a defined value due to the AND operation.
                     However, if we commute the AND inside the SUBREG then
                     they no longer have defined values and the meaning of
-                    the code has been changed.  */
+                    the code has been changed.
+                    Also C1 should not change value in the smaller mode,
+                    see PR67028 (a positive C1 can become negative in the
+                    smaller mode, so that the AND does no longer mask the
+                    upper bits).  */
                  && (0
 #ifdef WORD_REGISTER_OPERATIONS
                      || (mode_width > GET_MODE_PRECISION (tmode)
-                         && mode_width <= BITS_PER_WORD)
+                         && mode_width <= BITS_PER_WORD
+                         && trunc_int_for_mode (c1, tmode) == (HOST_WIDE_INT) c1)
 #endif
                      || (mode_width <= GET_MODE_PRECISION (tmode)
                          && subreg_lowpart_p (XEXP (op0, 0))))
-                 && CONST_INT_P (XEXP (op0, 1))
                  && mode_width <= HOST_BITS_PER_WIDE_INT
                  && HWI_COMPUTABLE_MODE_P (tmode)
-                 && ((c1 = INTVAL (XEXP (op0, 1))) & ~mask) == 0
+                 && (c1 & ~mask) == 0
                  && (c1 & ~GET_MODE_MASK (tmode)) == 0
                  && c1 != mask
                  && c1 != GET_MODE_MASK (tmode))
index 052a9d3..3b19caa 100644 (file)
@@ -4055,11 +4055,11 @@ ix86_option_override_internal (bool main_args_p,
   if (opts_set->x_ix86_incoming_stack_boundary_arg)
     {
       if (opts->x_ix86_incoming_stack_boundary_arg
-         < (TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 4 : 2)
+         < (TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 3 : 2)
          || opts->x_ix86_incoming_stack_boundary_arg > 12)
        error ("-mincoming-stack-boundary=%d is not between %d and 12",
               opts->x_ix86_incoming_stack_boundary_arg,
-              TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 4 : 2);
+              TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 3 : 2);
       else
        {
          ix86_user_incoming_stack_boundary
@@ -5201,6 +5201,14 @@ ix86_set_current_function (tree fndecl)
        TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
     }
   ix86_previous_fndecl = fndecl;
+
+  /* 64-bit MS and SYSV ABI have different set of call used registers.
+     Avoid expensive re-initialization of init_regs each time we switch
+     function context.  */
+  if (TARGET_64BIT
+      && (call_used_regs[SI_REG]
+         == (cfun->machine->call_abi == MS_ABI)))
+    reinit_regs ();
 }
 
 \f
@@ -6344,17 +6352,6 @@ ix86_call_abi_override (const_tree fndecl)
     cfun->machine->call_abi = ix86_function_type_abi (TREE_TYPE (fndecl));
 }
 
-/* 64-bit MS and SYSV ABI have different set of call used registers.  Avoid
-   expensive re-initialization of init_regs each time we switch function context
-   since this is needed only during RTL expansion.  */
-static void
-ix86_maybe_switch_abi (void)
-{
-  if (TARGET_64BIT &&
-      call_used_regs[SI_REG] == (cfun->machine->call_abi == MS_ABI))
-    reinit_regs ();
-}
-
 /* Return 1 if pseudo register should be created and used to hold
    GOT address for PIC code.  */
 bool
@@ -8211,7 +8208,8 @@ ix86_function_value_regno_p (const unsigned int regno)
     case SI_REG:
       return TARGET_64BIT && ix86_cfun_abi () != MS_ABI;
 
-    case FIRST_BND_REG:
+    case BND0_REG:
+    case BND1_REG:
       return chkp_function_instrumented_p (current_function_decl);
 
       /* Complex values are returned in %st(0)/%st(1) pair.  */
@@ -10104,11 +10102,14 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
   frame->nregs = ix86_nsaved_regs ();
   frame->nsseregs = ix86_nsaved_sseregs ();
 
-  /* 64-bit MS ABI seem to require stack alignment to be always 16 except for
-     function prologues and leaf.  */
+  /* 64-bit MS ABI seem to require stack alignment to be always 16,
+     except for function prologues, leaf functions and when the defult
+     incoming stack boundary is overriden at command line or via
+     force_align_arg_pointer attribute.  */
   if ((TARGET_64BIT_MS_ABI && crtl->preferred_stack_boundary < 128)
       && (!crtl->is_leaf || cfun->calls_alloca != 0
-          || ix86_current_function_calls_tls_descriptor))
+         || ix86_current_function_calls_tls_descriptor
+         || ix86_incoming_stack_boundary < 128))
     {
       crtl->preferred_stack_boundary = 128;
       crtl->stack_alignment_needed = 128;
@@ -10207,10 +10208,14 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
   if (frame->nsseregs)
     {
       /* The only ABI that has saved SSE registers (Win64) also has a
-         16-byte aligned default stack, and thus we don't need to be
-        within the re-aligned local stack frame to save them.  */
-      gcc_assert (INCOMING_STACK_BOUNDARY >= 128);
-      offset = (offset + 16 - 1) & -16;
+        16-byte aligned default stack, and thus we don't need to be
+        within the re-aligned local stack frame to save them.  In case
+        incoming stack boundary is aligned to less than 16 bytes,
+        unaligned move of SSE register will be emitted, so there is
+        no point to round up the SSE register save area outside the
+        re-aligned local stack frame to 16 bytes.  */
+      if (ix86_incoming_stack_boundary >= 128)
+       offset = (offset + 16 - 1) & -16;
       offset += frame->nsseregs * 16;
     }
   frame->sse_reg_save_offset = offset;
@@ -10220,7 +10225,7 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
      sure that no value happens to be the same before and after, force
      the alignment computation below to add a non-zero value.  */
   if (stack_realign_fp)
-    offset = (offset + stack_alignment_needed) & -stack_alignment_needed;
+    offset = (offset + stack_alignment_needed - 1) & -stack_alignment_needed;
 
   /* Va-arg area */
   frame->va_arg_size = ix86_varargs_gpr_size + ix86_varargs_fpr_size;
@@ -10433,15 +10438,24 @@ ix86_emit_save_reg_using_mov (machine_mode mode, unsigned int regno,
 {
   struct machine_function *m = cfun->machine;
   rtx reg = gen_rtx_REG (mode, regno);
+  rtx unspec = NULL_RTX;
   rtx mem, addr, base, insn;
+  unsigned int align;
 
   addr = choose_baseaddr (cfa_offset);
   mem = gen_frame_mem (mode, addr);
 
-  /* For SSE saves, we need to indicate the 128-bit alignment.  */
-  set_mem_align (mem, GET_MODE_ALIGNMENT (mode));
+  /* The location is aligned up to INCOMING_STACK_BOUNDARY.  */
+  align = MIN (GET_MODE_ALIGNMENT (mode), INCOMING_STACK_BOUNDARY);
+  set_mem_align (mem, align);
+
+  /* SSE saves are not within re-aligned local stack frame.
+     In case INCOMING_STACK_BOUNDARY is misaligned, we have
+     to emit unaligned store.  */
+  if (mode == V4SFmode && align < 128)
+    unspec = gen_rtx_UNSPEC (mode, gen_rtvec (1, reg), UNSPEC_STOREU);
 
-  insn = emit_move_insn (mem, reg);
+  insn = emit_insn (gen_rtx_SET (VOIDmode, mem, unspec ? unspec : reg));
   RTX_FRAME_RELATED_P (insn) = 1;
 
   base = addr;
@@ -10489,6 +10503,9 @@ ix86_emit_save_reg_using_mov (machine_mode mode, unsigned int regno,
       mem = gen_rtx_MEM (mode, addr);
       add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (VOIDmode, mem, reg));
     }
+  else if (unspec)
+    add_reg_note (insn, REG_CFA_EXPRESSION,
+                 gen_rtx_SET (VOIDmode, mem, reg));
 }
 
 /* Emit code to save registers using MOV insns.
@@ -10705,6 +10722,25 @@ find_drap_reg (void)
     }
 }
 
+/* Handle a "force_align_arg_pointer" attribute.  */
+
+static tree
+ix86_handle_force_align_arg_pointer_attribute (tree *node, tree name,
+                                              tree, int, bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_TYPE
+      && TREE_CODE (*node) != METHOD_TYPE
+      && TREE_CODE (*node) != FIELD_DECL
+      && TREE_CODE (*node) != TYPE_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+              name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Return minimum incoming stack alignment.  */
 
 static unsigned int
@@ -10719,7 +10755,6 @@ ix86_minimum_incoming_stack_boundary (bool sibcall)
      if -mstackrealign is used, it isn't used for sibcall check and
      estimated stack alignment is 128bit.  */
   else if (!sibcall
-          && !TARGET_64BIT
           && ix86_force_align_arg_pointer
           && crtl->stack_alignment_estimated == 128)
     incoming_stack_boundary = MIN_STACK_BOUNDARY;
@@ -11026,8 +11061,6 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
       release_scratch_register_on_entry (&sr);
     }
 
-  gcc_assert (cfun->machine->fs.cfa_reg != stack_pointer_rtx);
-
   /* Even if the stack pointer isn't the CFA register, we need to correctly
      describe the adjustments made to it, in particular differentiate the
      frame-related ones from the frame-unrelated ones.  */
@@ -11251,7 +11284,11 @@ ix86_finalize_stack_realign_flags (void)
       && !crtl->accesses_prior_frames
       && !cfun->calls_alloca
       && !crtl->calls_eh_return
-      && !(flag_stack_check && STACK_CHECK_MOVING_SP)
+      /* See ira_setup_eliminable_regset for the rationale.  */
+      && !(STACK_CHECK_MOVING_SP
+          && flag_stack_check
+          && flag_exceptions
+          && cfun->can_throw_non_call_exceptions)
       && !ix86_frame_pointer_required ()
       && get_frame_size () == 0
       && ix86_nsaved_sseregs () == 0
@@ -11578,7 +11615,7 @@ ix86_expand_prologue (void)
          pointer is no longer valid.  As for the value of sp_offset,
         see ix86_compute_frame_layout, which we need to match in order
         to pass verification of stack_pointer_offset at the end.  */
-      m->fs.sp_offset = (m->fs.sp_offset + align_bytes) & -align_bytes;
+      m->fs.sp_offset = (m->fs.sp_offset + align_bytes - 1) & -align_bytes;
       m->fs.sp_valid = false;
     }
 
@@ -11991,11 +12028,26 @@ ix86_emit_restore_sse_regs_using_mov (HOST_WIDE_INT cfa_offset,
       {
        rtx reg = gen_rtx_REG (V4SFmode, regno);
        rtx mem;
+       unsigned int align;
 
        mem = choose_baseaddr (cfa_offset);
        mem = gen_rtx_MEM (V4SFmode, mem);
-       set_mem_align (mem, 128);
-       emit_move_insn (reg, mem);
+
+       /* The location is aligned up to INCOMING_STACK_BOUNDARY.  */
+       align = MIN (GET_MODE_ALIGNMENT (V4SFmode), INCOMING_STACK_BOUNDARY);
+       set_mem_align (mem, align);
+
+       /* SSE saves are not within re-aligned local stack frame.
+          In case INCOMING_STACK_BOUNDARY is misaligned, we have
+          to emit unaligned load.  */
+       if (align < 128)
+         {
+           rtx unspec = gen_rtx_UNSPEC (V4SFmode, gen_rtvec (1, mem),
+                                        UNSPEC_LOADU);
+           emit_insn (gen_rtx_SET (VOIDmode, reg, unspec));
+         }
+       else
+         emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
 
        ix86_add_cfa_restore_note (NULL_RTX, reg, cfa_offset);
 
@@ -25140,7 +25192,8 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
       dst = change_address (dst, BLKmode, destreg);
       set_mem_align (dst, desired_align * BITS_PER_UNIT);
       epilogue_size_needed = 0;
-      if (need_zero_guard && !min_size)
+      if (need_zero_guard
+         && min_size < (unsigned HOST_WIDE_INT) size_needed)
        {
          /* It is possible that we copied enough so the main loop will not
             execute.  */
@@ -25272,7 +25325,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
          max_size -= align_bytes;
        }
       if (need_zero_guard
-         && !min_size
+         && min_size < (unsigned HOST_WIDE_INT) size_needed
          && (count < (unsigned HOST_WIDE_INT) size_needed
              || (align_bytes == 0
                  && count < ((unsigned HOST_WIDE_INT) size_needed
@@ -25557,7 +25610,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
 
   /* Avoid branch in fixing the byte.  */
   tmpreg = gen_lowpart (QImode, tmpreg);
-  emit_insn (gen_addqi3_cc (tmpreg, tmpreg, tmpreg));
+  emit_insn (gen_addqi3_cconly_overflow (tmpreg, tmpreg));
   tmp = gen_rtx_REG (CCmode, FLAGS_REG);
   cmp = gen_rtx_LTU (VOIDmode, tmp, const0_rtx);
   emit_insn (ix86_gen_sub3_carry (out, out, GEN_INT (3), tmp, cmp));
@@ -39522,60 +39575,57 @@ rdseed_step:
       return target;
 
     case IX86_BUILTIN_SBB32:
-      icode = CODE_FOR_subsi3_carry;
+      icode = CODE_FOR_subborrowsi;
       mode0 = SImode;
-      goto addcarryx;
+      goto handlecarry;
 
     case IX86_BUILTIN_SBB64:
-      icode = CODE_FOR_subdi3_carry;
+      icode = CODE_FOR_subborrowdi;
       mode0 = DImode;
-      goto addcarryx;
+      goto handlecarry;
 
     case IX86_BUILTIN_ADDCARRYX32:
-      icode = TARGET_ADX ? CODE_FOR_adcxsi3 : CODE_FOR_addsi3_carry;
+      icode = CODE_FOR_addcarrysi;
       mode0 = SImode;
-      goto addcarryx;
+      goto handlecarry;
 
     case IX86_BUILTIN_ADDCARRYX64:
-      icode = TARGET_ADX ? CODE_FOR_adcxdi3 : CODE_FOR_adddi3_carry;
+      icode = CODE_FOR_addcarrydi;
       mode0 = DImode;
 
-addcarryx:
+    handlecarry:
       arg0 = CALL_EXPR_ARG (exp, 0); /* unsigned char c_in.  */
       arg1 = CALL_EXPR_ARG (exp, 1); /* unsigned int src1.  */
       arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2.  */
       arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out.  */
 
-      op0 = gen_reg_rtx (QImode);
-
-      /* Generate CF from input operand.  */
       op1 = expand_normal (arg0);
       op1 = copy_to_mode_reg (QImode, convert_to_mode (QImode, op1, 1));
-      emit_insn (gen_addqi3_cc (op0, op1, constm1_rtx));
 
-      /* Gen ADCX instruction to compute X+Y+CF.  */
       op2 = expand_normal (arg1);
-      op3 = expand_normal (arg2);
-
-      if (!REG_P (op2))
+      if (!register_operand (op2, mode0))
        op2 = copy_to_mode_reg (mode0, op2);
-      if (!REG_P (op3))
-       op3 = copy_to_mode_reg (mode0, op3);
-
-      op0 = gen_reg_rtx (mode0);
 
-      op4 = gen_rtx_REG (CCCmode, FLAGS_REG);
-      pat = gen_rtx_LTU (VOIDmode, op4, const0_rtx);
-      emit_insn (GEN_FCN (icode) (op0, op2, op3, op4, pat));
+      op3 = expand_normal (arg2);
+      if (!register_operand (op3, mode0))
+       op3 = copy_to_mode_reg (mode0, op3);
 
-      /* Store the result.  */
       op4 = expand_normal (arg3);
       if (!address_operand (op4, VOIDmode))
        {
          op4 = convert_memory_address (Pmode, op4);
          op4 = copy_addr_to_reg (op4);
        }
-      emit_move_insn (gen_rtx_MEM (mode0, op4), op0);
+
+      /* Generate CF from input operand.  */
+      emit_insn (gen_addqi3_cconly_overflow (op1, constm1_rtx));
+
+      /* Generate instruction that consumes CF.  */
+      op0 = gen_reg_rtx (mode0);
+
+      op1 = gen_rtx_REG (CCCmode, FLAGS_REG);
+      pat = gen_rtx_LTU (mode0, op1, const0_rtx);
+      emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat));
 
       /* Return current CF value.  */
       if (target == 0)
@@ -39583,6 +39633,10 @@ addcarryx:
 
       PUT_MODE (pat, QImode);
       emit_insn (gen_rtx_SET (VOIDmode, target, pat));
+
+      /* Store the result.  */
+      emit_move_insn (gen_rtx_MEM (mode0, op4), op0);
+
       return target;
 
     case IX86_BUILTIN_READ_FLAGS:
@@ -41758,11 +41812,24 @@ ix86_cannot_change_mode_class (machine_mode from, machine_mode to,
 
   if (MAYBE_SSE_CLASS_P (regclass) || MAYBE_MMX_CLASS_P (regclass))
     {
+      int from_size = GET_MODE_SIZE (from);
+      int to_size = GET_MODE_SIZE (to);
+
       /* Vector registers do not support QI or HImode loads.  If we don't
         disallow a change to these modes, reload will assume it's ok to
         drop the subreg from (subreg:SI (reg:HI 100) 0).  This affects
         the vec_dupv4hi pattern.  */
-      if (GET_MODE_SIZE (from) < 4)
+      if (from_size < 4)
+       return true;
+
+      /* Further, we cannot allow word_mode subregs of full vector modes.
+         Otherwise the middle-end will assume it's ok to store to
+         (subreg:DI (reg:TI 100) 0) in order to modify only the low 64 bits
+         of the 128-bit register.  However, after reload the subreg will
+         be dropped leaving a plain DImode store.  This is indistinguishable
+         from a "normal" DImode move, and so we're justified to use movsd,
+         which modifies the entire 128-bit register.  */
+      if (to_size == UNITS_PER_WORD && from_size > UNITS_PER_WORD)
        return true;
     }
 
@@ -46836,7 +46903,7 @@ static const struct attribute_spec ix86_attribute_table[] =
     true },
   /* force_align_arg_pointer says this function realigns the stack at entry.  */
   { (const char *)&ix86_force_align_arg_pointer_string, 0, 0,
-    false, true,  true, ix86_handle_cconv_attribute, false },
+    false, true,  true, ix86_handle_force_align_arg_pointer_attribute, false },
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
   { "dllimport", 0, 0, false, false, false, handle_dll_attribute, false },
   { "dllexport", 0, 0, false, false, false, handle_dll_attribute, false },
@@ -48957,6 +49024,62 @@ expand_vec_perm_even_odd_pack (struct expand_vec_perm_d *d)
   return true;
 }
 
+/* A subroutine of expand_vec_perm_even_odd_1.  Implement extract-even
+   and extract-odd permutations of two V64QI operands
+   with two "shifts", two "truncs" and one "concat" insns for "odd"
+   and two "truncs" and one concat insn for "even."
+   Have already failed all two instruction sequences.  */
+
+static bool
+expand_vec_perm_even_odd_trunc (struct expand_vec_perm_d *d)
+{
+  rtx t1, t2, t3, t4;
+  unsigned i, odd, nelt = d->nelt;
+
+  if (!TARGET_AVX512BW
+      || d->one_operand_p
+      || d->vmode != V64QImode)
+    return false;
+
+  /* Check that permutation is even or odd.  */
+  odd = d->perm[0];
+  if (odd > 1)
+    return false;
+
+  for (i = 1; i < nelt; ++i)
+    if (d->perm[i] != 2 * i + odd)
+      return false;
+
+  if (d->testing_p)
+    return true;
+
+
+  if (odd)
+    {
+      t1 = gen_reg_rtx (V32HImode);
+      t2 = gen_reg_rtx (V32HImode);
+      emit_insn (gen_lshrv32hi3 (t1,
+                                gen_lowpart (V32HImode, d->op0),
+                                GEN_INT (8)));
+      emit_insn (gen_lshrv32hi3 (t2,
+                                gen_lowpart (V32HImode, d->op1),
+                                GEN_INT (8)));
+    }
+  else
+    {
+      t1 = gen_lowpart (V32HImode, d->op0);
+      t2 = gen_lowpart (V32HImode, d->op1);
+    }
+
+  t3 = gen_reg_rtx (V32QImode);
+  t4 = gen_reg_rtx (V32QImode);
+  emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t3, t1));
+  emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t4, t2));
+  emit_insn (gen_avx_vec_concatv64qi (d->target, t3, t4));
+
+  return true;
+}
+
 /* A subroutine of ix86_expand_vec_perm_builtin_1.  Implement extract-even
    and extract-odd permutations.  */
 
@@ -49059,6 +49182,9 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
     case V32QImode:
       return expand_vec_perm_even_odd_pack (d);
 
+    case V64QImode:
+      return expand_vec_perm_even_odd_trunc (d);
+
     case V4DImode:
       if (!TARGET_AVX2)
        {
@@ -49520,6 +49646,8 @@ ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
 
   /* Try sequences of four instructions.  */
 
+  if (expand_vec_perm_even_odd_trunc (d))
+    return true;
   if (expand_vec_perm_vpshufb2_vpermq (d))
     return true;
 
@@ -50396,6 +50524,10 @@ ix86_expand_pinsr (rtx *operands)
            return false;
          }
 
+       /* Reject insertions to misaligned positions.  */
+       if (pos & (size-1))
+         return false;
+
        rtx d = dst;
        if (GET_MODE (dst) != dstmode)
          d = gen_reg_rtx (dstmode);
@@ -51521,7 +51653,7 @@ ix86_destroy_cost_data (void *data)
 static unsigned HOST_WIDE_INT
 ix86_memmodel_check (unsigned HOST_WIDE_INT val)
 {
-  unsigned HOST_WIDE_INT model = val & MEMMODEL_MASK;
+  enum memmodel model = memmodel_from_int (val);
   bool strong;
 
   if (val & ~(unsigned HOST_WIDE_INT)(IX86_HLE_ACQUIRE|IX86_HLE_RELEASE
@@ -51532,14 +51664,14 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val)
               "Unknown architecture specific memory model");
       return MEMMODEL_SEQ_CST;
     }
-  strong = (model == MEMMODEL_ACQ_REL || model == MEMMODEL_SEQ_CST);
-  if (val & IX86_HLE_ACQUIRE && !(model == MEMMODEL_ACQUIRE || strong))
+  strong = (is_mm_acq_rel (model) || is_mm_seq_cst (model));
+  if (val & IX86_HLE_ACQUIRE && !(is_mm_acquire (model) || strong))
     {
       warning (OPT_Winvalid_memory_model,
               "HLE_ACQUIRE not used with ACQUIRE or stronger memory model");
       return MEMMODEL_SEQ_CST | IX86_HLE_ACQUIRE;
     }
-   if (val & IX86_HLE_RELEASE && !(model == MEMMODEL_RELEASE || strong))
+  if (val & IX86_HLE_RELEASE && !(is_mm_release (model) || strong))
     {
       warning (OPT_Winvalid_memory_model,
               "HLE_RELEASE not used with RELEASE or stronger memory model");
@@ -52312,9 +52444,6 @@ ix86_binds_local_p (const_tree exp)
 #undef TARGET_CAN_INLINE_P
 #define TARGET_CAN_INLINE_P ix86_can_inline_p
 
-#undef TARGET_EXPAND_TO_RTL_HOOK
-#define TARGET_EXPAND_TO_RTL_HOOK ix86_maybe_switch_abi
-
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P ix86_legitimate_address_p
 
index de43f06..d5a5263 100644 (file)
@@ -747,7 +747,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 #define MAIN_STACK_BOUNDARY (TARGET_64BIT ? 128 : 32)
 
 /* Minimum stack boundary.  */
-#define MIN_STACK_BOUNDARY (TARGET_64BIT ? (TARGET_SSE ? 128 : 64) : 32)
+#define MIN_STACK_BOUNDARY BITS_PER_WORD
 
 /* Boundary (in *bits*) on which the stack pointer prefers to be
    aligned; the compiler cannot rely on having this alignment.  */
@@ -1429,7 +1429,7 @@ enum reg_class
 { 0x1ff1ffff,0xffffffe0,   0x1f },       /* FLOAT_INT_SSE_REGS */        \
        { 0x0,       0x0, 0x1fc0 },       /* MASK_EVEX_REGS */           \
        { 0x0,       0x0, 0x1fe0 },       /* MASK_REGS */                 \
-{ 0xffffffff,0xffffffff, 0x1fff }                                        \
+{ 0xffffffff,0xffffffff,0x1ffff }                                        \
 }
 
 /* The same information, inverted:
index 2937293..8b1d372 100644 (file)
   UNSPEC_SAHF
   UNSPEC_PARITY
   UNSPEC_FSTCW
-  UNSPEC_ADD_CARRY
   UNSPEC_FLDCW
   UNSPEC_REP
   UNSPEC_LD_MPIC       ; load_macho_picbase
 (define_attr "isa" "base,x64,x64_sse4,x64_sse4_noavx,x64_avx,nox64,
                    sse2,sse2_noavx,sse3,sse4,sse4_noavx,avx,noavx,
                    avx2,noavx2,bmi,bmi2,fma4,fma,avx512f,noavx512f,
-                   fma_avx512f,avx512bw,noavx512bw,avx512dq,noavx512dq"
+                   fma_avx512f,avx512bw,noavx512bw,avx512dq,noavx512dq,
+                   avx512vl,noavx512vl"
   (const_string "base"))
 
 (define_attr "enabled" ""
         (eq_attr "isa" "noavx512bw") (symbol_ref "!TARGET_AVX512BW")
         (eq_attr "isa" "avx512dq") (symbol_ref "TARGET_AVX512DQ")
         (eq_attr "isa" "noavx512dq") (symbol_ref "!TARGET_AVX512DQ")
+        (eq_attr "isa" "avx512vl") (symbol_ref "TARGET_AVX512VL")
+        (eq_attr "isa" "noavx512vl") (symbol_ref "!TARGET_AVX512VL")
        ]
        (const_int 1)))
 
 (define_code_attr plusminus_mnemonic
   [(plus "add") (ss_plus "adds") (us_plus "addus")
    (minus "sub") (ss_minus "subs") (us_minus "subus")])
-(define_code_attr plusminus_carry_mnemonic
-  [(plus "adc") (minus "sbb")])
 (define_code_attr multdiv_mnemonic
   [(mult "mul") (div "div")])
 
   "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)"
   "#"
   "reload_completed"
-  [(parallel [(set (reg:CC FLAGS_REG)
-                  (unspec:CC [(match_dup 1) (match_dup 2)]
-                             UNSPEC_ADD_CARRY))
+  [(parallel [(set (reg:CCC FLAGS_REG)
+                  (compare:CCC
+                    (plus:DWIH (match_dup 1) (match_dup 2))
+                    (match_dup 1)))
              (set (match_dup 0)
                   (plus:DWIH (match_dup 1) (match_dup 2)))])
    (parallel [(set (match_dup 3)
                   (plus:DWIH
-                    (match_dup 4)
                     (plus:DWIH
                       (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
-                      (match_dup 5))))
+                      (match_dup 4))
+                    (match_dup 5)))
              (clobber (reg:CC FLAGS_REG))])]
   "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);")
 
-(define_insn "*add<mode>3_cc"
-  [(set (reg:CC FLAGS_REG)
-       (unspec:CC
-         [(match_operand:SWI48 1 "nonimmediate_operand" "%0,0")
-          (match_operand:SWI48 2 "<general_operand>" "r<i>,rm")]
-         UNSPEC_ADD_CARRY))
-   (set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r")
-       (plus:SWI48 (match_dup 1) (match_dup 2)))]
-  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
-  "add{<imodesuffix>}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "alu")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "addqi3_cc"
-  [(set (reg:CC FLAGS_REG)
-       (unspec:CC
-         [(match_operand:QI 1 "nonimmediate_operand" "%0,0")
-          (match_operand:QI 2 "general_operand" "qn,qm")]
-         UNSPEC_ADD_CARRY))
-   (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
-       (plus:QI (match_dup 1) (match_dup 2)))]
-  "ix86_binary_operator_ok (PLUS, QImode, operands)"
-  "add{b}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "alu")
-   (set_attr "mode" "QI")])
-
 (define_insn "*add<mode>_1"
   [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r")
        (plus:SWI48
                   (minus:DWIH (match_dup 1) (match_dup 2)))])
    (parallel [(set (match_dup 3)
                   (minus:DWIH
-                    (match_dup 4)
-                    (plus:DWIH
-                      (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
-                      (match_dup 5))))
+                    (minus:DWIH
+                      (match_dup 4)
+                      (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)))
+                    (match_dup 5)))
              (clobber (reg:CC FLAGS_REG))])]
   "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);")
 
 \f
 ;; Add with carry and subtract with borrow
 
-(define_expand "<plusminus_insn><mode>3_carry"
-  [(parallel
-    [(set (match_operand:SWI 0 "nonimmediate_operand")
-         (plusminus:SWI
-           (match_operand:SWI 1 "nonimmediate_operand")
-           (plus:SWI (match_operator:SWI 4 "ix86_carry_flag_operator"
-                      [(match_operand 3 "flags_reg_operand")
-                       (const_int 0)])
-                     (match_operand:SWI 2 "<general_operand>"))))
-     (clobber (reg:CC FLAGS_REG))])]
-  "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)")
-
-(define_insn "*<plusminus_insn><mode>3_carry"
+(define_insn "add<mode>3_carry"
   [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
-       (plusminus:SWI
-         (match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0")
+       (plus:SWI
          (plus:SWI
-           (match_operator 3 "ix86_carry_flag_operator"
-            [(reg FLAGS_REG) (const_int 0)])
-           (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))))
+           (match_operator:SWI 4 "ix86_carry_flag_operator"
+            [(match_operand 3 "flags_reg_operand") (const_int 0)])
+           (match_operand:SWI 1 "nonimmediate_operand" "%0,0"))
+         (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
-  "<plusminus_carry_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}"
+  "adc{<imodesuffix>}\t{%2, %0|%0, %2}"
   [(set_attr "type" "alu")
    (set_attr "use_carry" "1")
    (set_attr "pent_pair" "pu")
 (define_insn "*addsi3_carry_zext"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
-         (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
-                  (plus:SI (match_operator 3 "ix86_carry_flag_operator"
-                            [(reg FLAGS_REG) (const_int 0)])
-                           (match_operand:SI 2 "x86_64_general_operand" "rme")))))
+         (plus:SI
+           (plus:SI (match_operator:SI 3 "ix86_carry_flag_operator"
+                     [(reg FLAGS_REG) (const_int 0)])
+                    (match_operand:SI 1 "register_operand" "%0"))
+           (match_operand:SI 2 "x86_64_general_operand" "rme"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
   "adc{l}\t{%2, %k0|%k0, %2}"
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "SI")])
 
+;; There is no point to generate ADCX instruction. ADC is shorter and faster.
+
+(define_insn "addcarry<mode>"
+  [(set (reg:CCC FLAGS_REG)
+       (compare:CCC
+         (plus:SWI48
+           (plus:SWI48
+             (match_operator:SWI48 4 "ix86_carry_flag_operator"
+              [(match_operand 3 "flags_reg_operand") (const_int 0)])
+             (match_operand:SWI48 1 "nonimmediate_operand" "%0"))
+           (match_operand:SWI48 2 "nonimmediate_operand" "rm"))
+         (match_dup 1)))
+   (set (match_operand:SWI48 0 "register_operand" "=r")
+       (plus:SWI48 (plus:SWI48 (match_op_dup 4
+                                [(match_dup 3) (const_int 0)])
+                               (match_dup 1))
+                   (match_dup 2)))]
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
+  "adc{<imodesuffix>}\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "use_carry" "1")
+   (set_attr "pent_pair" "pu")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "sub<mode>3_carry"
+  [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
+       (minus:SWI
+         (minus:SWI
+           (match_operand:SWI 1 "nonimmediate_operand" "0,0")
+           (match_operator:SWI 4 "ix86_carry_flag_operator"
+            [(match_operand 3 "flags_reg_operand") (const_int 0)]))
+         (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m")))
+   (clobber (reg:CC FLAGS_REG))]
+  "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
+  "sbb{<imodesuffix>}\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "use_carry" "1")
+   (set_attr "pent_pair" "pu")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "*subsi3_carry_zext"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
-         (minus:SI (match_operand:SI 1 "register_operand" "0")
-                   (plus:SI (match_operator 3 "ix86_carry_flag_operator"
-                             [(reg FLAGS_REG) (const_int 0)])
-                            (match_operand:SI 2 "x86_64_general_operand" "rme")))))
+         (minus:SI
+           (minus:SI
+             (match_operand:SI 1 "register_operand" "0")
+             (match_operator:SI 3 "ix86_carry_flag_operator"
+              [(reg FLAGS_REG) (const_int 0)]))
+           (match_operand:SI 2 "x86_64_general_operand" "rme"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
   "sbb{l}\t{%2, %k0|%k0, %2}"
   [(set_attr "type" "alu")
+   (set_attr "use_carry" "1")
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "SI")])
-\f
-;; ADCX instruction
 
-(define_insn "adcx<mode>3"
+(define_insn "subborrow<mode>"
   [(set (reg:CCC FLAGS_REG)
        (compare:CCC
+         (match_operand:SWI48 1 "nonimmediate_operand" "0")
          (plus:SWI48
-           (match_operand:SWI48 1 "nonimmediate_operand" "%0")
-           (plus:SWI48
-             (match_operator 4 "ix86_carry_flag_operator"
-              [(match_operand 3 "flags_reg_operand") (const_int 0)])
-             (match_operand:SWI48 2 "nonimmediate_operand" "rm")))
-         (const_int 0)))
+           (match_operator:SWI48 4 "ix86_carry_flag_operator"
+            [(match_operand 3 "flags_reg_operand") (const_int 0)])
+           (match_operand:SWI48 2 "nonimmediate_operand" "rm"))))
    (set (match_operand:SWI48 0 "register_operand" "=r")
-       (plus:SWI48 (match_dup 1)
-                   (plus:SWI48 (match_op_dup 4
-                                [(match_dup 3) (const_int 0)])
-                               (match_dup 2))))]
-  "TARGET_ADX && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
-  "adcx\t{%2, %0|%0, %2}"
+       (minus:SWI48 (minus:SWI48 (match_dup 1)
+                                 (match_op_dup 4
+                                  [(match_dup 3) (const_int 0)]))
+                    (match_dup 2)))]
+  "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
+  "sbb{<imodesuffix>}\t{%2, %0|%0, %2}"
   [(set_attr "type" "alu")
    (set_attr "use_carry" "1")
+   (set_attr "pent_pair" "pu")
    (set_attr "mode" "<MODE>")])
 \f
 ;; Overflow setting add instructions
 
+(define_expand "addqi3_cconly_overflow"
+  [(parallel
+     [(set (reg:CCC FLAGS_REG)
+          (compare:CCC
+            (plus:QI
+              (match_operand:QI 0 "nonimmediate_operand")
+              (match_operand:QI 1 "general_operand"))
+            (match_dup 0)))
+      (clobber (match_scratch:QI 2))])]
+  "!(MEM_P (operands[0]) && MEM_P (operands[1]))")
+
 (define_insn "*add<mode>3_cconly_overflow"
   [(set (reg:CCC FLAGS_REG)
        (compare:CCC
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_AVX512F && reload_completed"
    [(parallel [(set (match_dup 0)
-                   (xor:HI (match_dup 0)
-                           (match_dup 1)))
+                   (xor:SWI1248x (match_dup 0)
+                                 (match_dup 1)))
               (clobber (reg:CC FLAGS_REG))])
     (set (match_dup 0)
-        (not:HI (match_dup 0)))])
+        (not:SWI1248x (match_dup 0)))])
 
 ;;There are kortrest[bdq] but no intrinsics for them.
 ;;We probably don't need to implement them.
   [(set (match_operand:HI 0 "register_operand" "=k")
        (ior:HI
          (ashift:HI
-           (match_operand:HI 1 "register_operand" "k")
+           (zero_extend:HI (match_operand:QI 1 "register_operand" "k"))
            (const_int 8))
          (zero_extend:HI (match_operand:QI 2 "register_operand" "k"))))]
   "TARGET_AVX512F"
   [(set (match_operand:SI 0 "register_operand" "=k")
        (ior:SI
          (ashift:SI
-           (match_operand:SI 1 "register_operand" "k")
+           (zero_extend:SI (match_operand:HI 1 "register_operand" "k"))
            (const_int 16))
-         (zero_extend:SI (subreg:HI (match_operand:SI 2 "register_operand" "k") 0))))]
+         (zero_extend:SI (match_operand:HI 2 "register_operand" "k"))))]
   "TARGET_AVX512BW"
   "kunpckwd\t{%2, %1, %0|%0, %1, %2}"
   [(set_attr "mode" "SI")])
   [(set (match_operand:DI 0 "register_operand" "=k")
        (ior:DI
          (ashift:DI
-           (match_operand:DI 1 "register_operand" "k")
+           (zero_extend:DI (match_operand:SI 1 "register_operand" "k"))
            (const_int 32))
-         (zero_extend:DI (subreg:SI (match_operand:DI 2 "register_operand" "k") 0))))]
+         (zero_extend:DI (match_operand:SI 2 "register_operand" "k"))))]
   "TARGET_AVX512BW"
   "kunpckdq\t{%2, %1, %0|%0, %1, %2}"
   [(set_attr "mode" "DI")])
      (set (match_dup 0) (neg:DWIH (match_dup 1)))])
    (parallel
     [(set (match_dup 2)
-         (plus:DWIH (match_dup 3)
-                    (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
-                               (const_int 0))))
+         (plus:DWIH (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
+                               (match_dup 3))
+                    (const_int 0)))
      (clobber (reg:CC FLAGS_REG))])
    (parallel
     [(set (match_dup 2)
 ;; We need to disable this for TARGET_SEH, as otherwise
 ;; shrink-wrapped prologue gets enabled too.  This might exceed
 ;; the maximum size of prologue in unwind information.
+;; Also disallow shrink-wrapping if using stack slot to pass the
+;; static chain pointer - the first instruction has to be pushl %esi
+;; and it can't be moved around, as we use alternate entry points
+;; in that case.
 
 (define_expand "simple_return"
   [(simple_return)]
-  "!TARGET_SEH"
+  "!TARGET_SEH && !ix86_static_chain_on_stack"
 {
   if (crtl->args.pops_args)
     {
        (call:P
         (mem:QI (match_operand 2 "constant_call_address_operand" "Bz"))
         (match_operand 3)))
-   (unspec:P [(match_operand 1 "tls_symbolic_operand")]
+   (unspec:P [(match_operand 1 "tls_symbolic_operand")
+             (reg:P SP_REG)]
             UNSPEC_TLS_GD)]
   "TARGET_64BIT"
 {
         (mem:QI (plus:DI (match_operand:DI 2 "register_operand" "b")
                          (match_operand:DI 3 "immediate_operand" "i")))
         (match_operand 4)))
-   (unspec:DI [(match_operand 1 "tls_symbolic_operand")]
-            UNSPEC_TLS_GD)]
+   (unspec:DI [(match_operand 1 "tls_symbolic_operand")
+              (reg:DI SP_REG)]
+             UNSPEC_TLS_GD)]
   "TARGET_64BIT && ix86_cmodel == CM_LARGE_PIC && !TARGET_PECOFF
    && GET_CODE (operands[3]) == CONST
    && GET_CODE (XEXP (operands[3], 0)) == UNSPEC
          (call:P
           (mem:QI (match_operand 2))
           (const_int 0)))
-     (unspec:P [(match_operand 1 "tls_symbolic_operand")]
+     (unspec:P [(match_operand 1 "tls_symbolic_operand")
+               (reg:P SP_REG)]
               UNSPEC_TLS_GD)])]
   "TARGET_64BIT"
   "ix86_tls_descriptor_calls_expanded_in_cfun = true;")
        (call:P
         (mem:QI (match_operand 1 "constant_call_address_operand" "Bz"))
         (match_operand 2)))
-   (unspec:P [(const_int 0)] UNSPEC_TLS_LD_BASE)]
+   (unspec:P [(reg:P SP_REG)] UNSPEC_TLS_LD_BASE)]
   "TARGET_64BIT"
 {
   output_asm_insn
         (mem:QI (plus:DI (match_operand:DI 1 "register_operand" "b")
                          (match_operand:DI 2 "immediate_operand" "i")))
         (match_operand 3)))
-   (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
+   (unspec:DI [(reg:DI SP_REG)] UNSPEC_TLS_LD_BASE)]
   "TARGET_64BIT && ix86_cmodel == CM_LARGE_PIC && !TARGET_PECOFF
    && GET_CODE (operands[2]) == CONST
    && GET_CODE (XEXP (operands[2], 0)) == UNSPEC
           (call:P
            (mem:QI (match_operand 1))
            (const_int 0)))
-      (unspec:P [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
+      (unspec:P [(reg:P SP_REG)] UNSPEC_TLS_LD_BASE)])]
   "TARGET_64BIT"
   "ix86_tls_descriptor_calls_expanded_in_cfun = true;")
 
index e5e5c35..f8aad90 100644 (file)
@@ -453,17 +453,18 @@ prepare_target_image (const char *target_compiler, int argc, char **argv)
   fork_execute (objcopy_argv[0], CONST_CAST (char **, objcopy_argv), false);
 
   /* Objcopy has created symbols, containing the input file name with
-     special characters replaced with '_'.  We are going to rename these
-     new symbols.  */
+     non-alphanumeric characters replaced by underscores.
+     We are going to rename these new symbols.  */
   size_t symbol_name_len = strlen (target_so_filename);
   char *symbol_name = XALLOCAVEC (char, symbol_name_len + 1);
-  for (size_t i = 0; i <= symbol_name_len; i++)
+  for (size_t i = 0; i < symbol_name_len; i++)
     {
       char c = target_so_filename[i];
-      if ((c == '/') || (c == '.'))
+      if (!ISALNUM (c))
        c = '_';
       symbol_name[i] = c;
     }
+  symbol_name[symbol_name_len] = '\0';
 
   char *opt_for_objcopy[3];
   opt_for_objcopy[0] = XALLOCAVEC (char, sizeof ("_binary__start=")
index 2873535..dc7f6a7 100644 (file)
   [(V16HI "TARGET_AVX2") V8HI
    (V8SI "TARGET_AVX2") V4SI])
 
-(define_mode_iterator VI124_AVX512F
-  [(V32QI "TARGET_AVX2") V16QI
+(define_mode_iterator VI124_AVX2_24_AVX512F_1_AVX512BW
+  [(V64QI "TARGET_AVX512BW") (V32QI "TARGET_AVX2") V16QI
    (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX2") V8HI
    (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX2") V4SI])
 
   [(V8SI "TARGET_AVX2") V4SI
    (V4DI "TARGET_AVX2") V2DI])
 
-(define_mode_iterator VI248_AVX2_8_AVX512F
-  [(V16HI "TARGET_AVX2") V8HI
-   (V8SI "TARGET_AVX2") V4SI
+(define_mode_iterator VI248_AVX2_8_AVX512F_24_AVX512BW
+  [(V32HI "TARGET_AVX512BW") (V16HI "TARGET_AVX2") V8HI
+   (V16SI "TARGET_AVX512BW") (V8SI "TARGET_AVX2") V4SI
    (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX2") V2DI])
 
 (define_mode_iterator VI248_AVX512BW_AVX512VL
   [(V16SI "TARGET_AVX512F") V8SI V4SI
    (V8DI "TARGET_AVX512F") V4DI V2DI])
 
+(define_mode_iterator VI48_AVX_AVX512F
+  [(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
+   (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI])
+
+(define_mode_iterator VI12_AVX_AVX512F
+  [ (V64QI "TARGET_AVX512F") (V32QI "TARGET_AVX") V16QI
+    (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI])
+
 (define_mode_iterator V48_AVX2
   [V4SF V2DF
    V8SF V4DF
    (set_attr "mode" "DF,DF,V1DF,V1DF,V1DF,V2DF,V1DF,V1DF,V1DF")])
 
 (define_insn "vec_dupv2df<mask_name>"
-  [(set (match_operand:V2DF 0 "register_operand"     "=x,v")
+  [(set (match_operand:V2DF 0 "register_operand"     "=x,x,v")
        (vec_duplicate:V2DF
-         (match_operand:DF 1 "nonimmediate_operand" " 0,vm")))]
+         (match_operand:DF 1 "nonimmediate_operand" " 0,xm,vm")))]
   "TARGET_SSE2 && <mask_avx512vl_condition>"
   "@
    unpcklpd\t%0, %0
-   %vmovddup\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
-  [(set_attr "isa" "noavx,sse3")
+   %vmovddup\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}
+   vmovddup\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}"
+  [(set_attr "isa" "noavx,sse3,avx512vl")
    (set_attr "type" "sselog1")
-   (set_attr "prefix" "orig,maybe_vex")
-   (set_attr "mode" "V2DF,DF")])
+   (set_attr "prefix" "orig,maybe_vex,evex")
+   (set_attr "mode" "V2DF,DF,DF")])
 
 (define_insn "*vec_concatv2df"
-  [(set (match_operand:V2DF 0 "register_operand"     "=x,v,v,x,x,v,x,x")
+  [(set (match_operand:V2DF 0 "register_operand"     "=x,x,v,x,v,x,x,v,x,x")
        (vec_concat:V2DF
-         (match_operand:DF 1 "nonimmediate_operand" " 0,v,m,0,x,m,0,0")
-         (match_operand:DF 2 "vector_move_operand"  " x,v,1,m,m,C,x,m")))]
+         (match_operand:DF 1 "nonimmediate_operand" " 0,x,v,m,m,0,x,m,0,0")
+         (match_operand:DF 2 "vector_move_operand"  " x,x,v,1,1,m,m,C,x,m")))]
   "TARGET_SSE"
   "@
    unpcklpd\t{%2, %0|%0, %2}
    vunpcklpd\t{%2, %1, %0|%0, %1, %2}
+   vunpcklpd\t{%2, %1, %0|%0, %1, %2}
    %vmovddup\t{%1, %0|%0, %1}
+   vmovddup\t{%1, %0|%0, %1}
    movhpd\t{%2, %0|%0, %2}
    vmovhpd\t{%2, %1, %0|%0, %1, %2}
    %vmovsd\t{%1, %0|%0, %1}
    movlhps\t{%2, %0|%0, %2}
    movhps\t{%2, %0|%0, %2}"
-  [(set_attr "isa" "sse2_noavx,avx,sse3,sse2_noavx,avx,sse2,noavx,noavx")
+  [(set_attr "isa" "sse2_noavx,avx,avx512vl,sse3,avx512vl,sse2_noavx,avx,sse2,noavx,noavx")
    (set (attr "type")
      (if_then_else
-       (eq_attr "alternative" "0,1,2")
+       (eq_attr "alternative" "0,1,2,3,4")
        (const_string "sselog")
        (const_string "ssemov")))
-   (set_attr "prefix_data16" "*,*,*,1,*,*,*,*")
-   (set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex,orig,orig")
-   (set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,DF,V4SF,V2SF")])
+   (set (attr "prefix_data16")
+       (if_then_else (eq_attr "alternative" "5")
+                     (const_string "1")
+                     (const_string "*")))
+   (set_attr "prefix" "orig,vex,evex,maybe_vex,evex,orig,vex,maybe_vex,orig,orig")
+   (set_attr "mode" "V2DF,V2DF,V2DF, DF, DF, V1DF,V1DF,DF,V4SF,V2SF")])
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
       (match_operand:<avx512fmaskmode> 2 "register_operand")))]
   "TARGET_AVX512F")
 
-(define_insn "*avx512bw_<code>v32hiv32qi2"
+(define_insn "avx512bw_<code>v32hiv32qi2"
   [(set (match_operand:V32QI 0 "nonimmediate_operand" "=v,m")
        (any_truncate:V32QI
            (match_operand:V32HI 1 "register_operand" "v,v")))]
 })
 
 (define_insn "<mask_codefor><code><mode>3<mask_name>"
-  [(set (match_operand:VI 0 "register_operand" "=x,v")
-       (any_logic:VI
-         (match_operand:VI 1 "nonimmediate_operand" "%0,v")
-         (match_operand:VI 2 "nonimmediate_operand" "xm,vm")))]
+  [(set (match_operand:VI48_AVX_AVX512F 0 "register_operand" "=x,v")
+       (any_logic:VI48_AVX_AVX512F
+         (match_operand:VI48_AVX_AVX512F 1 "nonimmediate_operand" "%0,v")
+         (match_operand:VI48_AVX_AVX512F 2 "nonimmediate_operand" "xm,vm")))]
   "TARGET_SSE && <mask_mode512bit_condition>
    && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
 {
         case V4DImode:
         case V4SImode:
         case V2DImode:
-          if (TARGET_AVX512VL)
+          tmp = TARGET_AVX512VL ? "p<logic><ssemodesuffix>" : "p<logic>";
+          break;
+        default:
+          gcc_unreachable ();
+      }
+      break;
+
+   case MODE_V8SF:
+      gcc_assert (TARGET_AVX);
+   case MODE_V4SF:
+      gcc_assert (TARGET_SSE);
+      gcc_assert (!<mask_applied>);
+      tmp = "<logic>ps";
+      break;
+
+   default:
+      gcc_unreachable ();
+   }
+
+  switch (which_alternative)
+    {
+    case 0:
+      if (<mask_applied>)
+        ops = "v%s\t{%%2, %%0, %%0<mask_operand3_1>|%%0<mask_operand3_1>, %%0, %%2}";
+      else
+        ops = "%s\t{%%2, %%0|%%0, %%2}";
+      break;
+    case 1:
+      ops = "v%s\t{%%2, %%1, %%0<mask_operand3_1>|%%0<mask_operand3_1>, %%1, %%2}";
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  snprintf (buf, sizeof (buf), ops, tmp);
+  return buf;
+}
+  [(set_attr "isa" "noavx,avx")
+   (set_attr "type" "sselog")
+   (set (attr "prefix_data16")
+     (if_then_else
+       (and (eq_attr "alternative" "0")
+           (eq_attr "mode" "TI"))
+       (const_string "1")
+       (const_string "*")))
+   (set_attr "prefix" "<mask_prefix3>")
+   (set (attr "mode")
+       (cond [(and (match_test "<MODE_SIZE> == 16")
+                   (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL"))
+                (const_string "<ssePSmode>")
+              (match_test "TARGET_AVX2")
+                (const_string "<sseinsnmode>")
+              (match_test "TARGET_AVX")
+                (if_then_else
+                  (match_test "<MODE_SIZE> > 16")
+                  (const_string "V8SF")
+                  (const_string "<sseinsnmode>"))
+              (ior (not (match_test "TARGET_SSE2"))
+                   (match_test "optimize_function_for_size_p (cfun)"))
+                (const_string "V4SF")
+             ]
+             (const_string "<sseinsnmode>")))])
+
+(define_insn "*<code><mode>3"
+  [(set (match_operand:VI12_AVX_AVX512F 0 "register_operand" "=x,v")
+       (any_logic: VI12_AVX_AVX512F
+         (match_operand:VI12_AVX_AVX512F 1 "nonimmediate_operand" "%0,v")
+         (match_operand:VI12_AVX_AVX512F 2 "nonimmediate_operand" "xm,vm")))]
+  "TARGET_SSE && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+{
+  static char buf[64];
+  const char *ops;
+  const char *tmp;
+  const char *ssesuffix;
+
+  switch (get_attr_mode (insn))
+    {
+    case MODE_XI:
+      gcc_assert (TARGET_AVX512F);
+    case MODE_OI:
+      gcc_assert (TARGET_AVX2 || TARGET_AVX512VL);
+    case MODE_TI:
+      gcc_assert (TARGET_SSE2 || TARGET_AVX512VL);
+      switch (<MODE>mode)
+        {
+        case V64QImode:
+        case V32HImode:
+          if (TARGET_AVX512F)
           {
-            tmp = "p<logic><ssemodesuffix>";
+            tmp = "p<logic>";
+            ssesuffix = "q";
+            break;
+          }
+        case V32QImode:
+        case V16HImode:
+        case V16QImode:
+        case V8HImode:
+          if (TARGET_AVX512VL || TARGET_AVX2 || TARGET_SSE2)
+          {
+            tmp = "p<logic>";
+            ssesuffix = TARGET_AVX512VL ? "q" : "";
             break;
           }
         default:
-          tmp = TARGET_AVX512VL ? "p<logic>q" : "p<logic>";
+          gcc_unreachable ();
       }
       break;
 
-   case MODE_V16SF:
-      gcc_assert (TARGET_AVX512F);
    case MODE_V8SF:
       gcc_assert (TARGET_AVX);
    case MODE_V4SF:
       gcc_assert (TARGET_SSE);
-
       tmp = "<logic>ps";
+      ssesuffix = "";
       break;
 
    default:
     {
     case 0:
       ops = "%s\t{%%2, %%0|%%0, %%2}";
+      snprintf (buf, sizeof (buf), ops, tmp);
       break;
     case 1:
-      ops = "v%s\t{%%2, %%1, %%0<mask_operand3_1>|%%0<mask_operand3_1>, %%1, %%2}";
+      ops = "v%s%s\t{%%2, %%1, %%0|%%0, %%1, %%2}";
+      snprintf (buf, sizeof (buf), ops, tmp, ssesuffix);
       break;
     default:
       gcc_unreachable ();
     }
 
-  snprintf (buf, sizeof (buf), ops, tmp);
   return buf;
 }
   [(set_attr "isa" "noavx,avx")
 
 (define_expand "vec_pack_trunc_<mode>"
   [(match_operand:<ssepackmode> 0 "register_operand")
-   (match_operand:VI248_AVX2_8_AVX512F 1 "register_operand")
-   (match_operand:VI248_AVX2_8_AVX512F 2 "register_operand")]
+   (match_operand:VI248_AVX2_8_AVX512F_24_AVX512BW 1 "register_operand")
+   (match_operand:VI248_AVX2_8_AVX512F_24_AVX512BW 2 "register_operand")]
   "TARGET_SSE2"
 {
   rtx op1 = gen_lowpart (<ssepackmode>mode, operands[1]);
 
 (define_expand "vec_unpacks_lo_<mode>"
   [(match_operand:<sseunpackmode> 0 "register_operand")
-   (match_operand:VI124_AVX512F 1 "register_operand")]
+   (match_operand:VI124_AVX2_24_AVX512F_1_AVX512BW 1 "register_operand")]
   "TARGET_SSE2"
   "ix86_expand_sse_unpack (operands[0], operands[1], false, false); DONE;")
 
 (define_expand "vec_unpacks_hi_<mode>"
   [(match_operand:<sseunpackmode> 0 "register_operand")
-   (match_operand:VI124_AVX512F 1 "register_operand")]
+   (match_operand:VI124_AVX2_24_AVX512F_1_AVX512BW 1 "register_operand")]
   "TARGET_SSE2"
   "ix86_expand_sse_unpack (operands[0], operands[1], false, true); DONE;")
 
 (define_expand "vec_unpacku_lo_<mode>"
   [(match_operand:<sseunpackmode> 0 "register_operand")
-   (match_operand:VI124_AVX512F 1 "register_operand")]
+   (match_operand:VI124_AVX2_24_AVX512F_1_AVX512BW 1 "register_operand")]
   "TARGET_SSE2"
   "ix86_expand_sse_unpack (operands[0], operands[1], true, false); DONE;")
 
 (define_expand "vec_unpacku_hi_<mode>"
   [(match_operand:<sseunpackmode> 0 "register_operand")
-   (match_operand:VI124_AVX512F 1 "register_operand")]
+   (match_operand:VI124_AVX2_24_AVX512F_1_AVX512BW 1 "register_operand")]
   "TARGET_SSE2"
   "ix86_expand_sse_unpack (operands[0], operands[1], true, true); DONE;")
 
index 61a2a81..59573d4 100644 (file)
   [(match_operand:SI 0 "const_int_operand")]           ;; model
   ""
 {
-  enum memmodel model = (enum memmodel) (INTVAL (operands[0]) & MEMMODEL_MASK);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[0]));
 
   /* Unless this is a SEQ_CST fence, the i386 memory model is strong
      enough not to require barriers of any kind.  */
-  if (model == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     {
       rtx (*mfence_insn)(rtx);
       rtx mem;
                       UNSPEC_STA))]
   ""
 {
-  enum memmodel model = (enum memmodel) (INTVAL (operands[2]) & MEMMODEL_MASK);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
 
   if (<MODE>mode == DImode && !TARGET_64BIT)
     {
       operands[1] = force_reg (<MODE>mode, operands[1]);
 
       /* For seq-cst stores, when we lack MFENCE, use XCHG.  */
-      if (model == MEMMODEL_SEQ_CST && !(TARGET_64BIT || TARGET_SSE2))
+      if (is_mm_seq_cst (model) && !(TARGET_64BIT || TARGET_SSE2))
        {
          emit_insn (gen_atomic_exchange<mode> (gen_reg_rtx (<MODE>mode),
                                                operands[0], operands[1],
                                           operands[2]));
     }
   /* ... followed by an MFENCE, if required.  */
-  if (model == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     emit_insn (gen_mem_thread_fence (operands[2]));
   DONE;
 })
index 90fa13f..0ee8633 100644 (file)
@@ -263,6 +263,18 @@ enum function_class {
   function_c11_misc
 };
 
+/* Suppose that higher bits are target dependent. */
+#define MEMMODEL_MASK ((1<<16)-1)
+
+/* Legacy sync operations set this upper flag in the memory model.  This allows
+   targets that need to do something stronger for sync operations to
+   differentiate with their target patterns and issue a more appropriate insn
+   sequence.  See bugzilla 65697 for background.  */
+#define MEMMODEL_SYNC (1<<15)
+
+/* Memory model without SYNC bit for targets/operations that do not care.  */
+#define MEMMODEL_BASE_MASK (MEMMODEL_SYNC-1)
+
 /* Memory model types for the __atomic* builtins. 
    This must match the order in libstdc++-v3/include/bits/atomic_base.h.  */
 enum memmodel
@@ -273,12 +285,12 @@ enum memmodel
   MEMMODEL_RELEASE = 3,
   MEMMODEL_ACQ_REL = 4,
   MEMMODEL_SEQ_CST = 5,
-  MEMMODEL_LAST = 6
+  MEMMODEL_LAST = 6,
+  MEMMODEL_SYNC_ACQUIRE = MEMMODEL_ACQUIRE | MEMMODEL_SYNC,
+  MEMMODEL_SYNC_RELEASE = MEMMODEL_RELEASE | MEMMODEL_SYNC,
+  MEMMODEL_SYNC_SEQ_CST = MEMMODEL_SEQ_CST | MEMMODEL_SYNC
 };
 
-/* Suppose that higher bits are target dependent. */
-#define MEMMODEL_MASK ((1<<16)-1)
-
 /* Support for user-provided GGC and PCH markers.  The first parameter
    is a pointer to a pointer, the second a cookie.  */
 typedef void (*gt_pointer_operator) (void *, void *);
index 949225b..0df408c 100644 (file)
@@ -7002,6 +7002,39 @@ call_copy_ctor (tree a, tsubst_flags_t complain)
   return r;
 }
 
+/* Return true iff T refers to a base field.  */
+
+static bool
+is_base_field_ref (tree t)
+{
+  STRIP_NOPS (t);
+  if (TREE_CODE (t) == ADDR_EXPR)
+    t = TREE_OPERAND (t, 0);
+  if (TREE_CODE (t) == COMPONENT_REF)
+    t = TREE_OPERAND (t, 1);
+  if (TREE_CODE (t) == FIELD_DECL)
+    return DECL_FIELD_IS_BASE (t);
+  return false;
+}
+
+/* We can't elide a copy from a function returning by value to a base
+   subobject, as the callee might clobber tail padding.  Return true iff this
+   could be that case.  */
+
+static bool
+unsafe_copy_elision_p (tree target, tree exp)
+{
+  tree type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+  if (type == CLASSTYPE_AS_BASE (type))
+    return false;
+  if (!is_base_field_ref (target)
+      && resolves_to_fixed_type_p (target, NULL))
+    return false;
+  tree init = TARGET_EXPR_INITIAL (exp);
+  return (TREE_CODE (init) == AGGR_INIT_EXPR
+         && !AGGR_INIT_VIA_CTOR_P (init));
+}
+
 /* Subroutine of the various build_*_call functions.  Overload resolution
    has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
    ARGS is a TREE_LIST of the unconverted arguments to the call.  FLAGS is a
@@ -7419,7 +7452,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
          else if (trivial)
            return force_target_expr (DECL_CONTEXT (fn), arg, complain);
        }
-      else if (TREE_CODE (arg) == TARGET_EXPR || trivial)
+      else if (trivial
+              || (TREE_CODE (arg) == TARGET_EXPR
+                  && !unsafe_copy_elision_p (fa, arg)))
        {
          tree to = stabilize_reference (cp_build_indirect_ref (fa, RO_NULL,
                                                                complain));
index d59d351..f3ec826 100644 (file)
@@ -1989,14 +1989,23 @@ fixup_attribute_variants (tree t)
   if (!t)
     return;
 
+  tree attrs = TYPE_ATTRIBUTES (t);
+  unsigned align = TYPE_ALIGN (t);
+  bool user_align = TYPE_USER_ALIGN (t);
+
   for (variants = TYPE_NEXT_VARIANT (t);
        variants;
        variants = TYPE_NEXT_VARIANT (variants))
     {
       /* These are the two fields that check_qualified_type looks at and
         are affected by attributes.  */
-      TYPE_ATTRIBUTES (variants) = TYPE_ATTRIBUTES (t);
-      TYPE_ALIGN (variants) = TYPE_ALIGN (t);
+      TYPE_ATTRIBUTES (variants) = attrs;
+      unsigned valign = align;
+      if (TYPE_USER_ALIGN (variants))
+       valign = MAX (valign, TYPE_ALIGN (variants));
+      else
+       TYPE_USER_ALIGN (variants) = user_align;
+      TYPE_ALIGN (variants) = valign;
     }
 }
 \f
index e250726..ba9fd0e 100644 (file)
@@ -1750,7 +1750,38 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
       VERIFY_CONSTANT (ary);
       gcc_unreachable ();
     }
-  if (compare_tree_int (index, len) >= 0)
+
+  i = tree_fits_shwi_p (index) ? tree_to_shwi (index) : -1;
+  bool found = true;
+  if (TREE_CODE (ary) == CONSTRUCTOR && len
+      && (TREE_CODE (CONSTRUCTOR_ELT (ary, len-1)->index) == RANGE_EXPR
+         || compare_tree_int (CONSTRUCTOR_ELT (ary, len-1)->index, len-1)))
+    {
+      /* The last element doesn't match its position in the array; this must be
+        a sparse array from cxx_eval_store_expression.  So iterate.  */
+      found = false;
+      vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (ary);
+      constructor_elt *e;
+      for (unsigned ix = 0; vec_safe_iterate (v, ix, &e); ++ix)
+       {
+         if (TREE_CODE (e->index) == RANGE_EXPR)
+           {
+             tree lo = TREE_OPERAND (e->index, 0);
+             tree hi = TREE_OPERAND (e->index, 1);
+             if (tree_int_cst_le (lo, index) && tree_int_cst_le (index, hi))
+               found = true;
+           }
+         else if (tree_int_cst_equal (e->index, index))
+           found = true;
+         if (found)
+           {
+             i = ix;
+             break;
+           }
+       }
+    }
+
+  if (i >= len || !found)
     {
       if (tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary))))
        {
@@ -1767,14 +1798,14 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
       *non_constant_p = true;
       return t;
     }
-  else if (tree_int_cst_lt (index, integer_zero_node))
+  else if (i < 0)
     {
       if (!ctx->quiet)
        error ("negative array subscript");
       *non_constant_p = true;
       return t;
     }
-  i = tree_to_shwi (index);
+
   if (TREE_CODE (ary) == CONSTRUCTOR)
     return (*CONSTRUCTOR_ELTS (ary))[i].value;
   else if (elem_nchars == 1)
@@ -2719,10 +2750,13 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
     {
       /* Create a new CONSTRUCTOR in case evaluation of the initializer
         wants to modify it.  */
-      new_ctx.ctor = build_constructor (type, NULL);
       if (*valp == NULL_TREE)
-       *valp = new_ctx.ctor;
-      CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = true;
+       {
+         *valp = new_ctx.ctor = build_constructor (type, NULL);
+         CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = true;
+       }
+      else
+       new_ctx.ctor = *valp;
       new_ctx.object = target;
     }
 
index 4e525e0..6f13b01 100644 (file)
@@ -101,6 +101,7 @@ c-common.h, not after.
       DECLTYPE_FOR_INIT_CAPTURE (in DECLTYPE_TYPE)
       CONSTRUCTOR_NO_IMPLICIT_ZERO (in CONSTRUCTOR)
       TINFO_USED_TEMPLATE_ID (in TEMPLATE_INFO)
+      PACK_EXPANSION_SIZEOF_P (in *_PACK_EXPANSION)
    2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
       ICS_THIS_FLAG (in _CONV)
       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
@@ -3031,6 +3032,9 @@ extern void decl_shadowed_for_var_insert (tree, tree);
 /* True iff this pack expansion is within a function context.  */
 #define PACK_EXPANSION_LOCAL_P(NODE) TREE_LANG_FLAG_0 (NODE)
 
+/* True iff this pack expansion is for sizeof....  */
+#define PACK_EXPANSION_SIZEOF_P(NODE) TREE_LANG_FLAG_1 (NODE)
+
 /* Determine if this is an argument pack.  */
 #define ARGUMENT_PACK_P(NODE)                          \
   (TREE_CODE (NODE) == TYPE_ARGUMENT_PACK              \
@@ -4606,6 +4610,11 @@ extern GTY(()) vec<tree, va_gc> *local_classes;
 
 extern int at_eof;
 
+/* True if note_mangling_alias should enqueue mangling aliases for
+   later generation, rather than emitting them right away.  */
+
+extern bool defer_mangling_aliases;
+
 /* A list of namespace-scope objects which have constructors or
    destructors which reside in the global scope.  The decl is stored
    in the TREE_VALUE slot and the initializer is stored in the
@@ -5453,6 +5462,8 @@ extern tree finish_case_label                     (location_t, tree, tree);
 extern tree cxx_maybe_build_cleanup            (tree, tsubst_flags_t);
 
 /* in decl2.c */
+extern void note_mangling_alias                        (tree, tree);
+extern void generate_mangling_aliases          (void);
 extern bool check_java_method                  (tree);
 extern tree build_memfn_type                   (tree, tree, cp_cv_quals, cp_ref_qualifier);
 extern tree build_pointer_ptrmemfn_type        (tree);
@@ -5762,6 +5773,7 @@ extern bool reregister_specialization             (tree, tree, tree);
 extern tree instantiate_non_dependent_expr     (tree);
 extern tree instantiate_non_dependent_expr_sfinae (tree, tsubst_flags_t);
 extern tree instantiate_non_dependent_expr_internal (tree, tsubst_flags_t);
+extern bool variable_template_specialization_p  (tree);
 extern bool alias_type_or_template_p            (tree);
 extern bool alias_template_specialization_p     (const_tree);
 extern bool dependent_alias_template_spec_p     (const_tree);
@@ -5944,7 +5956,7 @@ extern tree perform_koenig_lookup         (tree, vec<tree, va_gc> *,
                                                 tsubst_flags_t);
 extern tree finish_call_expr                   (tree, vec<tree, va_gc> **, bool,
                                                 bool, tsubst_flags_t);
-extern tree finish_template_variable   (tree);
+extern tree finish_template_variable           (tree, tsubst_flags_t = tf_warning_or_error);
 extern tree finish_increment_expr              (tree, enum tree_code);
 extern tree finish_this_expr                   (void);
 extern tree finish_pseudo_destructor_expr       (tree, tree, tree, location_t);
@@ -6423,7 +6435,7 @@ extern bool cilk_valid_spawn                    (tree);
 /* In cp-ubsan.c */
 extern void cp_ubsan_maybe_instrument_member_call (tree);
 extern void cp_ubsan_instrument_member_accesses (tree *);
-extern tree cp_ubsan_maybe_instrument_downcast (location_t, tree, tree);
+extern tree cp_ubsan_maybe_instrument_downcast (location_t, tree, tree, tree);
 extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
 
 /* -- end of C++ */
index ce12263..6ffdab3 100644 (file)
@@ -276,13 +276,14 @@ cp_ubsan_instrument_member_accesses (tree *t_p)
 /* Instrument downcast.  */
 
 tree
-cp_ubsan_maybe_instrument_downcast (location_t loc, tree type, tree op)
+cp_ubsan_maybe_instrument_downcast (location_t loc, tree type,
+                                   tree intype, tree op)
 {
   if (!POINTER_TYPE_P (type)
+      || !POINTER_TYPE_P (intype)
       || !POINTER_TYPE_P (TREE_TYPE (op))
-      || !CLASS_TYPE_P (TREE_TYPE (type))
       || !CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (op)))
-      || !DERIVED_FROM_P (TREE_TYPE (TREE_TYPE (op)), TREE_TYPE (type)))
+      || !is_properly_derived_from (TREE_TYPE (type), TREE_TYPE (intype)))
     return NULL_TREE;
 
   return cp_ubsan_maybe_instrument_vptr (loc, op, TREE_TYPE (type), true,
index 9aa9006..10d50ae 100644 (file)
@@ -695,7 +695,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
     }
 
   /* FIXME remove when moving to c_fully_fold model.  */
-  e = scalar_constant_value (e);
+  if (!CLASS_TYPE_P (type))
+    e = scalar_constant_value (e);
   if (error_operand_p (e))
     return error_mark_node;
 
index 72c77ea..c9e98e9 100644 (file)
@@ -2907,14 +2907,16 @@ decl_jump_unsafe (tree decl)
   return 0;
 }
 
-/* A subroutine of check_previous_goto_1 to identify a branch to the user.  */
+/* A subroutine of check_previous_goto_1 and check_goto to identify a branch
+   to the user.  */
 
 static bool
-identify_goto (tree decl, const location_t *locus)
+identify_goto (tree decl, location_t loc, const location_t *locus,
+              diagnostic_t diag_kind)
 {
-  bool complained = (decl
-                    ? permerror (input_location, "jump to label %qD", decl)
-                    : permerror (input_location, "jump to case label"));
+  bool complained
+    = (decl ? emit_diagnostic (diag_kind, loc, 0, "jump to label %qD", decl)
+           : emit_diagnostic (diag_kind, loc, 0, "jump to case label"));
   if (complained && locus)
     inform (*locus, "  from here");
   return complained;
@@ -2931,15 +2933,17 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
                       bool exited_omp, const location_t *locus)
 {
   cp_binding_level *b;
-  bool identified = false, complained = false;
+  bool complained = false;
+  int identified = 0;
   bool saw_eh = false, saw_omp = false;
 
   if (exited_omp)
     {
-      complained = identify_goto (decl, locus);
+      complained = identify_goto (decl, input_location, locus, DK_ERROR);
       if (complained)
        inform (input_location, "  exits OpenMP structured block");
-      identified = saw_omp = true;
+      saw_omp = true;
+      identified = 2;
     }
 
   for (b = current_binding_level; b ; b = b->level_chain)
@@ -2956,8 +2960,9 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
 
          if (!identified)
            {
-             complained = identify_goto (decl, locus);
-             identified = true;
+             complained = identify_goto (decl, input_location, locus,
+                                         DK_PERMERROR);
+             identified = 1;
            }
          if (complained)
            {
@@ -2974,10 +2979,11 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
        break;
       if ((b->kind == sk_try || b->kind == sk_catch) && !saw_eh)
        {
-         if (!identified)
+         if (identified < 2)
            {
-             complained = identify_goto (decl, locus);
-             identified = true;
+             complained = identify_goto (decl, input_location, locus,
+                                         DK_ERROR);
+             identified = 2;
            }
          if (complained)
            {
@@ -2990,10 +2996,11 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
        }
       if (b->kind == sk_omp && !saw_omp)
        {
-         if (!identified)
+         if (identified < 2)
            {
-             complained = identify_goto (decl, locus);
-             identified = true;
+             complained = identify_goto (decl, input_location, locus,
+                                         DK_ERROR);
+             identified = 2;
            }
          if (complained)
            inform (input_location, "  enters OpenMP structured block");
@@ -3025,7 +3032,8 @@ void
 check_goto (tree decl)
 {
   struct named_label_entry *ent, dummy;
-  bool saw_catch = false, identified = false, complained = false;
+  bool saw_catch = false, complained = false;
+  int identified = 0;
   tree bad;
   unsigned ix;
 
@@ -3068,10 +3076,12 @@ check_goto (tree decl)
   if (ent->in_try_scope || ent->in_catch_scope
       || ent->in_omp_scope || !vec_safe_is_empty (ent->bad_decls))
     {
-      complained = permerror (input_location, "jump to label %q+D", decl);
-      if (complained)
-       inform (input_location, "  from here");
-      identified = true;
+      diagnostic_t diag_kind = DK_PERMERROR;
+      if (ent->in_try_scope || ent->in_catch_scope || ent->in_omp_scope)
+       diag_kind = DK_ERROR;
+      complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
+                                 &input_location, diag_kind);
+      identified = 1 + (diag_kind == DK_ERROR);
     }
 
   FOR_EACH_VEC_SAFE_ELT (ent->bad_decls, ix, bad)
@@ -3081,6 +3091,12 @@ check_goto (tree decl)
       if (u > 1 && DECL_ARTIFICIAL (bad))
        {
          /* Can't skip init of __exception_info.  */
+         if (identified == 1)
+           {
+             complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
+                                         &input_location, DK_ERROR);
+             identified = 2;
+           }
          if (complained)
            inform (DECL_SOURCE_LOCATION (bad), "  enters catch block");
          saw_catch = true;
@@ -3117,13 +3133,12 @@ check_goto (tree decl)
            break;
          if (b->kind == sk_omp)
            {
-             if (!identified)
+             if (identified < 2)
                {
-                 complained = permerror (input_location,
-                                         "jump to label %q+D", decl);
-                 if (complained)
-                   inform (input_location, "  from here");
-                 identified = true;
+                 complained = identify_goto (decl,
+                                             DECL_SOURCE_LOCATION (decl),
+                                             &input_location, DK_ERROR);
+                 identified = 2;
                }
              if (complained)
                inform (input_location, "  exits OpenMP structured block");
index f5d1e52..8d895fe 100644 (file)
@@ -118,9 +118,18 @@ static GTY(()) vec<tree, va_gc> *deferred_fns;
    sure are defined.  */
 static GTY(()) vec<tree, va_gc> *no_linkage_decls;
 
+/* A vector of alternating decls and identifiers, where the latter
+   is to be an alias for the former if the former is defined.  */
+static GTY(()) vec<tree, va_gc> *mangling_aliases;
+
 /* Nonzero if we're done parsing and into end-of-file activities.  */
 
 int at_eof;
+
+/* True if note_mangling_alias should enqueue mangling aliases for
+   later generation, rather than emitting them right away.  */
+
+bool defer_mangling_aliases = true;
 \f
 
 /* Return a member function type (a METHOD_TYPE), given FNTYPE (a
@@ -1742,6 +1751,9 @@ mark_vtable_entries (tree decl)
   tree fnaddr;
   unsigned HOST_WIDE_INT idx;
 
+  /* It's OK for the vtable to refer to deprecated virtual functions.  */
+  warning_sentinel w(warn_deprecated_decl);
+
   FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)),
                              idx, fnaddr)
     {
@@ -4232,8 +4244,12 @@ no_linkage_error (tree decl)
                TYPE_NAME (t));
     }
   else if (cxx_dialect >= cxx11)
-    permerror (DECL_SOURCE_LOCATION (decl), "%q#D, declared using local type "
-              "%qT, is used but never defined", decl, t);
+    {
+      if (TREE_CODE (decl) == VAR_DECL || !DECL_PURE_VIRTUAL_P (decl))
+       permerror (DECL_SOURCE_LOCATION (decl),
+                  "%q#D, declared using local type "
+                  "%qT, is used but never defined", decl, t);
+    }
   else if (TREE_CODE (decl) == VAR_DECL)
     warning_at (DECL_SOURCE_LOCATION (decl), 0, "type %qT with no linkage "
                "used to declare variable %q#D with linkage", t, decl);
@@ -4320,6 +4336,69 @@ handle_tls_init (void)
   expand_or_defer_fn (finish_function (0));
 }
 
+/* We're at the end of compilation, so generate any mangling aliases that
+   we've been saving up, if DECL is going to be output and ID2 isn't
+   already taken by another declaration.  */
+
+static void
+generate_mangling_alias (tree decl, tree id2)
+{
+  /* If there's a declaration already using this mangled name,
+     don't create a compatibility alias that conflicts.  */
+  if (IDENTIFIER_GLOBAL_VALUE (id2))
+    return;
+
+  struct cgraph_node *n = NULL;
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && !(n = cgraph_node::get (decl)))
+    /* Don't create an alias to an unreferenced function.  */
+    return;
+
+  tree alias = make_alias_for (decl, id2);
+  SET_IDENTIFIER_GLOBAL_VALUE (id2, alias);
+  DECL_IGNORED_P (alias) = 1;
+  TREE_PUBLIC (alias) = TREE_PUBLIC (decl);
+  DECL_VISIBILITY (alias) = DECL_VISIBILITY (decl);
+  if (vague_linkage_p (decl))
+    DECL_WEAK (alias) = 1;
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    n->create_same_body_alias (alias, decl);
+  else
+    varpool_node::create_extra_name_alias (alias, decl);
+}
+
+/* Note that we might want to emit an alias with the symbol ID2 for DECL at
+   the end of translation, for compatibility across bugs in the mangling
+   implementation.  */
+
+void
+note_mangling_alias (tree decl ATTRIBUTE_UNUSED, tree id2 ATTRIBUTE_UNUSED)
+{
+#ifdef ASM_OUTPUT_DEF
+  if (!defer_mangling_aliases)
+    generate_mangling_alias (decl, id2);
+  else
+    {
+      vec_safe_push (mangling_aliases, decl);
+      vec_safe_push (mangling_aliases, id2);
+    }
+#endif
+}
+
+/* Emit all mangling aliases that were deferred up to this point.  */
+
+void
+generate_mangling_aliases ()
+{
+  while (!vec_safe_is_empty (mangling_aliases))
+    {
+      tree id2 = mangling_aliases->pop();
+      tree decl = mangling_aliases->pop();
+      generate_mangling_alias (decl, id2);
+    }
+  defer_mangling_aliases = false;
+}
+
 /* The entire file is now complete.  If requested, dump everything
    to a file.  */
 
@@ -4681,6 +4760,8 @@ cp_write_global_declarations (void)
     }
   while (reconsider);
 
+  generate_mangling_aliases ();
+
   /* All used inline functions must have a definition at this point.  */
   FOR_EACH_VEC_SAFE_ELT (deferred_fns, i, decl)
     {
index ce43f86..4bcd281 100644 (file)
@@ -1230,7 +1230,8 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags)
        if (args == error_mark_node)
          pp_string (pp, M_("<template arguments error>"));
        else if (args)
-         dump_template_argument_list (pp, args, flags);
+         dump_template_argument_list
+           (pp, args, flags|TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS);
        pp_cxx_end_template_argument_list (pp);
       }
       break;
index 04c09d8..ac11224 100644 (file)
@@ -851,6 +851,18 @@ build_field_list (tree t, tree list, int *uses_unions_p)
   return list;
 }
 
+/* Return the innermost aggregate scope for FIELD, whether that is
+   the enclosing class or an anonymous aggregate within it.  */
+
+static tree
+innermost_aggr_scope (tree field)
+{
+  if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
+    return TREE_TYPE (field);
+  else
+    return DECL_CONTEXT (field);
+}
+
 /* The MEM_INITS are a TREE_LIST.  The TREE_PURPOSE of each list gives
    a FIELD_DECL or BINFO in T that needs initialization.  The
    TREE_VALUE gives the initializer, or list of initializer arguments.
@@ -994,7 +1006,7 @@ sort_mem_initializers (tree t, tree mem_inits)
 
          /* See if this field is a member of a union, or a member of a
             structure contained in a union, etc.  */
-         for (ctx = DECL_CONTEXT (field);
+         for (ctx = innermost_aggr_scope (field);
               !same_type_p (ctx, t);
               ctx = TYPE_CONTEXT (ctx))
            if (TREE_CODE (ctx) == UNION_TYPE
@@ -1027,8 +1039,9 @@ sort_mem_initializers (tree t, tree mem_inits)
               union { struct { int i; int j; }; };
 
             initializing both `i' and `j' makes sense.  */
-         ctx = common_enclosing_class (DECL_CONTEXT (field),
-                                       DECL_CONTEXT (TREE_PURPOSE (*last_p)));
+         ctx = common_enclosing_class
+           (innermost_aggr_scope (field),
+            innermost_aggr_scope (TREE_PURPOSE (*last_p)));
 
          if (ctx && TREE_CODE (ctx) == UNION_TYPE)
            {
index 5b151c1..779e4cb 100644 (file)
@@ -1054,6 +1054,12 @@ maybe_add_lambda_conv_op (tree type)
   if (generic_lambda_p)
     fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop));
 
+  /* Don't UBsan this function; we're deliberately calling op() with a null
+     object argument.  */
+  tree attrs = build_tree_list (get_identifier ("no_sanitize_undefined"),
+                               NULL_TREE);
+  cplus_decl_attributes (&fn, attrs, 0);
+
   add_method (type, fn, NULL_TREE);
 
   if (nested)
index 23c95b6..4e0ed22 100644 (file)
@@ -1160,7 +1160,7 @@ write_template_prefix (const tree node)
      So, for the example above, `Outer<int>::Inner' is represented as a
      substitution candidate by a TREE_LIST whose purpose is `Outer<int>'
      and whose value is `Outer<T>::Inner<U>'.  */
-  if (TYPE_P (context))
+  if (context && TYPE_P (context))
     substitution = build_tree_list (context, templ);
   else
     substitution = templ;
@@ -2771,7 +2771,9 @@ write_expression (tree expr)
     {
       tree fn = TREE_OPERAND (expr, 0);
       if (is_overloaded_fn (fn))
-       fn = DECL_NAME (get_first_fn (fn));
+       fn = get_first_fn (fn);
+      if (DECL_P (fn))
+       fn = DECL_NAME (fn);
       if (IDENTIFIER_OPNAME_P (fn))
        write_string ("on");
       write_unqualified_id (fn);
@@ -3582,30 +3584,7 @@ mangle_decl (const tree decl)
                     flag_abi_compat_version, id2);
        }
 
-#ifdef ASM_OUTPUT_DEF
-      /* If there's a declaration already using this mangled name,
-        don't create a compatibility alias that conflicts.  */
-      if (IDENTIFIER_GLOBAL_VALUE (id2))
-       return;
-
-      struct cgraph_node *n = NULL;
-      if (TREE_CODE (decl) == FUNCTION_DECL
-         && !(n = cgraph_node::get (decl)))
-       /* Don't create an alias to an unreferenced function.  */
-       return;
-
-      tree alias = make_alias_for (decl, id2);
-      SET_IDENTIFIER_GLOBAL_VALUE (id2, alias);
-      DECL_IGNORED_P (alias) = 1;
-      TREE_PUBLIC (alias) = TREE_PUBLIC (decl);
-      DECL_VISIBILITY (alias) = DECL_VISIBILITY (decl);
-      if (vague_linkage_p (decl))
-       DECL_WEAK (alias) = 1;
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-       n->create_same_body_alias (alias, decl);
-      else
-       varpool_node::create_extra_name_alias (alias, decl);
-#endif
+      note_mangling_alias (decl, id2);
     }
 }
 
index 2d20e09..a2dd880 100644 (file)
@@ -294,7 +294,11 @@ maybe_thunk_body (tree fn, bool force)
     }
   else if (HAVE_COMDAT_GROUP)
     {
+      /* At eof, defer creation of mangling aliases temporarily.  */
+      bool save_defer_mangling_aliases = defer_mangling_aliases;
+      defer_mangling_aliases = true;
       tree comdat_group = cdtor_comdat_group (fns[1], fns[0]);
+      defer_mangling_aliases = save_defer_mangling_aliases;
       cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
       cgraph_node::get_create (fns[1])->add_to_same_comdat_group
        (cgraph_node::get_create (fns[0]));
@@ -305,6 +309,9 @@ maybe_thunk_body (tree fn, bool force)
           virtual, it goes into the same comdat group as well.  */
        cgraph_node::get_create (fns[2])->add_to_same_comdat_group
          (symtab_node::get (fns[0]));
+      /* Emit them now that the thunks are same comdat group aliases.  */
+      if (!save_defer_mangling_aliases)
+       generate_mangling_aliases ();
       TREE_PUBLIC (fn) = false;
       DECL_EXTERNAL (fn) = false;
       DECL_INTERFACE_KNOWN (fn) = true;
index db9301f..e6def9a 100644 (file)
@@ -4432,7 +4432,8 @@ cp_parser_primary_expression (cp_parser *parser,
        parser->greater_than_is_operator_p
          = saved_greater_than_is_operator_p;
        /* Consume the `)'.  */
-       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)
+           && !cp_parser_uncommitted_to_tentative_parse_p (parser))
          cp_parser_skip_to_end_of_statement (parser);
 
        return expr;
@@ -24431,6 +24432,7 @@ cp_parser_sizeof_pack (cp_parser *parser)
   else if (TREE_CODE (expr) == CONST_DECL)
     expr = DECL_INITIAL (expr);
   expr = make_pack_expansion (expr);
+  PACK_EXPANSION_SIZEOF_P (expr) = true;
 
   if (paren)
     cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
@@ -28181,8 +28183,8 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location
   if (num == error_mark_node)
     return list;
   num = fold_non_dependent_expr (num);
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
-      || !tree_fits_shwi_p (num)
+  if (!tree_fits_shwi_p (num)
+      || !INTEGRAL_TYPE_P (TREE_TYPE (num))
       || (n = tree_to_shwi (num)) <= 0
       || (int) n != n)
     {
index db10608..51cc245 100644 (file)
@@ -3222,6 +3222,13 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
                        ppd, ppd->visited);
          *walk_subtrees = 0;
        }
+      else if (variable_template_specialization_p (t))
+       {
+         cp_walk_tree (&DECL_TI_ARGS (t),
+                       find_parameter_packs_r,
+                       ppd, ppd->visited);
+         *walk_subtrees = 0;
+       }
       break;
 
     case BASES:
@@ -5323,6 +5330,17 @@ instantiate_non_dependent_expr (tree expr)
   return instantiate_non_dependent_expr_sfinae (expr, tf_error);
 }
 
+/* True iff T is a specialization of a variable template.  */
+
+bool
+variable_template_specialization_p (tree t)
+{
+  if (!VAR_P (t) || !DECL_LANG_SPECIFIC (t) || !DECL_TEMPLATE_INFO (t))
+    return false;
+  tree tmpl = DECL_TI_TEMPLATE (t);
+  return variable_template_p (tmpl);
+}
+
 /* Return TRUE iff T is a type alias, a TEMPLATE_DECL for an alias
    template declaration, or a TYPE_DECL for an alias declaration.  */
 
@@ -8161,14 +8179,14 @@ lookup_template_class (tree d1, tree arglist, tree in_decl, tree context,
 tree
 lookup_template_variable (tree templ, tree arglist)
 {
-  tree type = unknown_type_node;
+  tree type = NULL_TREE;
   return build2 (TEMPLATE_ID_EXPR, type, templ, arglist);
 }
 
 /* Instantiate a variable declaration from a TEMPLATE_ID_EXPR for use. */
 
 tree
-finish_template_variable (tree var)
+finish_template_variable (tree var, tsubst_flags_t complain)
 {
   tree templ = TREE_OPERAND (var, 0);
 
@@ -8177,7 +8195,6 @@ finish_template_variable (tree var)
   arglist = add_outermost_template_args (tmpl_args, arglist);
 
   tree parms = DECL_TEMPLATE_PARMS (templ);
-  tsubst_flags_t complain = tf_warning_or_error;
   arglist = coerce_innermost_template_parms (parms, arglist, templ, complain,
                                             /*req_all*/true,
                                             /*use_default*/true);
@@ -10159,12 +10176,17 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
        }
     }
 
-  /* If the expansion is just T..., return the matching argument pack.  */
+  /* If the expansion is just T..., return the matching argument pack, unless
+     we need to call convert_from_reference on all the elements.  This is an
+     important optimization; see c++/68422.  */
   if (!unsubstituted_packs
       && TREE_PURPOSE (packs) == pattern)
     {
       tree args = ARGUMENT_PACK_ARGS (TREE_VALUE (packs));
+      /* Types need no adjustment, nor does sizeof..., and if we still have
+        some pack expansion args we won't do anything yet.  */
       if (TREE_CODE (t) == TYPE_PACK_EXPANSION
+         || PACK_EXPANSION_SIZEOF_P (t)
          || pack_expansion_args_count (args))
        return args;
       /* Otherwise use the normal path so we get convert_from_reference.  */
@@ -11547,6 +11569,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
          {
            DECL_ORIGINAL_TYPE (r) = NULL_TREE;
            set_underlying_type (r);
+           if (TYPE_DECL_ALIAS_P (r) && type != error_mark_node)
+             /* An alias template specialization can be dependent
+                even if its underlying type is not.  */
+             TYPE_DEPENDENT_P_VALID (TREE_TYPE (r)) = false;
          }
 
        layout_decl (r, 0);
@@ -13089,8 +13115,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
              if (r)
                {
                  /* Make sure that the one we found is the one we want.  */
-                 tree ctx = tsubst (DECL_CONTEXT (t), args,
-                                    complain, in_decl);
+                 tree ctx = DECL_CONTEXT (t);
+                 if (DECL_LANG_SPECIFIC (ctx) && DECL_TEMPLATE_INFO (ctx))
+                   ctx = tsubst (ctx, args, complain, in_decl);
                  if (ctx != DECL_CONTEXT (r))
                    r = NULL_TREE;
                }
@@ -13138,7 +13165,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        }
       else
        r = t;
-      mark_used (r);
+      if (!mark_used (r, complain) && !(complain & tf_error))
+       return error_mark_node;
       return r;
 
     case NAMESPACE_DECL:
@@ -13203,7 +13231,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case SIZEOF_EXPR:
       if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
         {
-
           tree expanded, op = TREE_OPERAND (t, 0);
          int len = 0;
 
@@ -13229,6 +13256,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
            {
              if (TREE_CODE (expanded) == TREE_VEC)
                expanded = TREE_VEC_ELT (expanded, len - 1);
+             else
+               PACK_EXPANSION_SIZEOF_P (expanded) = true;
 
              if (TYPE_P (expanded))
                return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR, 
@@ -14714,6 +14743,19 @@ tsubst_copy_and_build (tree t,
 
        if (targs)
          targs = tsubst_template_args (targs, args, complain, in_decl);
+       if (targs == error_mark_node)
+         return error_mark_node;
+
+       if (variable_template_p (templ))
+         {
+           templ = lookup_template_variable (templ, targs);
+           if (!any_dependent_template_arguments_p (targs))
+             {
+               templ = finish_template_variable (templ, complain);
+               mark_used (templ);
+             }
+           RETURN (convert_from_reference (templ));
+         }
 
        if (TREE_CODE (templ) == COMPONENT_REF)
          {
@@ -15826,6 +15868,8 @@ tsubst_copy_and_build (tree t,
 
        LAMBDA_EXPR_THIS_CAPTURE (r) = NULL_TREE;
 
+       insert_pending_capture_proxies ();
+
        RETURN (build_lambda_object (r));
       }
 
@@ -16112,6 +16156,8 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
   /* The DECL_TI_TEMPLATE should always be the immediate parent
      template, not the most general template.  */
   DECL_TI_TEMPLATE (fndecl) = tmpl;
+  if (VAR_P (fndecl))
+    DECL_TI_ARGS (fndecl) = targ_ptr;
 
   /* Now we know the specialization, compute access previously
      deferred.  */
index 0031acd..1864f90 100644 (file)
@@ -736,7 +736,7 @@ protected_accessible_p (tree decl, tree derived, tree binfo)
     Here DERIVED is a possible P, DECL is m and BINFO_TYPE (binfo) is N.  */
 
   /* If DERIVED isn't derived from N, then it can't be a P.  */
-  if (!DERIVED_FROM_P (BINFO_TYPE (binfo), derived))
+  if (!DERIVED_FROM_P (context_for_name_lookup (decl), derived))
     return 0;
 
   access = access_in_type (derived, decl);
index 82ef642..feba03d 100644 (file)
@@ -3580,6 +3580,7 @@ finish_id_expression (tree id_expression,
        {
          decl = finish_template_variable (decl);
          mark_used (decl);
+         decl = convert_from_reference (decl);
        }
       else if (scope)
        {
@@ -4294,8 +4295,6 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
     {
       if (error_operand_p (t))
        return error_mark_node;
-      if (type_dependent_expression_p (t))
-       return NULL_TREE;
       if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
        {
          if (processing_template_decl)
@@ -4318,6 +4317,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
                    omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
          return error_mark_node;
        }
+      if (type_dependent_expression_p (t))
+       return NULL_TREE;
       t = convert_from_reference (t);
       return t;
     }
@@ -5332,7 +5333,8 @@ finish_omp_clauses (tree clauses)
          goto check_dup_generic;
        case OMP_CLAUSE_LINEAR:
          t = OMP_CLAUSE_DECL (c);
-         if (!type_dependent_expression_p (t)
+         if ((VAR_P (t) || TREE_CODE (t) == PARM_DECL)
+             && !type_dependent_expression_p (t)
              && !INTEGRAL_TYPE_P (TREE_TYPE (t))
              && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
            {
@@ -5359,7 +5361,9 @@ finish_omp_clauses (tree clauses)
          else
            {
              t = mark_rvalue_use (t);
-             if (!processing_template_decl)
+             if (!processing_template_decl
+                 && (VAR_P (OMP_CLAUSE_DECL (c))
+                     || TREE_CODE (OMP_CLAUSE_DECL (c)) == PARM_DECL))
                {
                  if (TREE_CODE (OMP_CLAUSE_DECL (c)) == PARM_DECL)
                    t = maybe_constant_value (t);
@@ -6452,7 +6456,8 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
   iter_init = build_x_modify_expr (elocus,
                                   iter, PLUS_EXPR, iter_init,
                                   tf_warning_or_error);
-  iter_init = build1 (NOP_EXPR, void_type_node, iter_init);
+  if (iter_init != error_mark_node)
+    iter_init = build1 (NOP_EXPR, void_type_node, iter_init);
   finish_expr_stmt (iter_init);
   finish_expr_stmt (build_x_modify_expr (elocus,
                                         last, NOP_EXPR, decl,
index 1408e3c..2279255 100644 (file)
@@ -6477,7 +6477,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       if (flag_sanitize & SANITIZE_VPTR)
        {
          tree ubsan_check
-           = cp_ubsan_maybe_instrument_downcast (input_location, type, expr);
+           = cp_ubsan_maybe_instrument_downcast (input_location, type,
+                                                 intype, expr);
          if (ubsan_check)
            expr = ubsan_check;
        }
@@ -6618,7 +6619,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       if (flag_sanitize & SANITIZE_VPTR)
        {
          tree ubsan_check
-           = cp_ubsan_maybe_instrument_downcast (input_location, type, expr);
+           = cp_ubsan_maybe_instrument_downcast (input_location, type,
+                                                 intype, expr);
          if (ubsan_check)
            expr = ubsan_check;
        }
index 3f4aacd..27b71b2 100644 (file)
@@ -1323,22 +1323,23 @@ df_lr_verify_transfer_functions (void)
 
 \f
 /*----------------------------------------------------------------------------
-   LIVE AND MUST-INITIALIZED REGISTERS.
+   LIVE AND MAY-INITIALIZED REGISTERS.
 
    This problem first computes the IN and OUT bitvectors for the
-   must-initialized registers problems, which is a forward problem.
-   It gives the set of registers for which we MUST have an available
-   definition on any path from the entry block to the entry/exit of
-   a basic block.  Sets generate a definition, while clobbers kill
+   may-initialized registers problems, which is a forward problem.
+   It gives the set of registers for which we MAY have an available
+   definition, i.e. for which there is an available definition on
+   at least one path from the entry block to the entry/exit of a
+   basic block.  Sets generate a definition, while clobbers kill
    a definition.
 
    In and out bitvectors are built for each basic block and are indexed by
    regnum (see df.h for details).  In and out bitvectors in struct
-   df_live_bb_info actually refers to the must-initialized problem;
+   df_live_bb_info actually refers to the may-initialized problem;
 
    Then, the in and out sets for the LIVE problem itself are computed.
    These are the logical AND of the IN and OUT sets from the LR problem
-   and the must-initialized problem.
+   and the may-initialized problem.
 ----------------------------------------------------------------------------*/
 
 /* Private data used to verify the solution for this problem.  */
@@ -1545,7 +1546,7 @@ df_live_confluence_n (edge e)
 }
 
 
-/* Transfer function for the forwards must-initialized problem.  */
+/* Transfer function for the forwards may-initialized problem.  */
 
 static bool
 df_live_transfer_function (int bb_index)
@@ -1569,7 +1570,7 @@ df_live_transfer_function (int bb_index)
 }
 
 
-/* And the LR info with the must-initialized registers, to produce the LIVE info.  */
+/* And the LR info with the may-initialized registers to produce the LIVE info.  */
 
 static void
 df_live_finalize (bitmap all_blocks)
index 2196406..c431622 100644 (file)
@@ -138,7 +138,6 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
   new (context->printer) pretty_printer ();
 
   memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
-  context->some_warnings_are_errors = false;
   context->warning_as_error_requested = false;
   context->n_opts = n_opts;
   context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
@@ -204,7 +203,7 @@ void
 diagnostic_finish (diagnostic_context *context)
 {
   /* Some of the errors may actually have been warnings.  */
-  if (context->some_warnings_are_errors)
+  if (diagnostic_kind_count (context, DK_WERROR))
     {
       /* -Werror was given.  */
       if (context->warning_as_error_requested)
@@ -646,9 +645,10 @@ diagnostic_classify_diagnostic (diagnostic_context *context,
       /* Record the command-line status, so we can reset it back on DK_POP. */
       if (old_kind == DK_UNSPECIFIED)
        {
-         old_kind = context->option_enabled (option_index,
-                                             context->option_state)
-           ? DK_WARNING : DK_IGNORED;
+         old_kind = !context->option_enabled (option_index,
+                                              context->option_state)
+           ? DK_IGNORED : (context->warning_as_error_requested
+                           ? DK_ERROR : DK_WARNING);
          context->classify_diagnostic[option_index] = old_kind;
        }
 
@@ -810,9 +810,6 @@ diagnostic_report_diagnostic (diagnostic_context *context,
        return false;
     }
 
-  if (orig_diag_kind == DK_WARNING && diagnostic->kind == DK_ERROR)
-    context->some_warnings_are_errors = true;
-
   context->lock++;
 
   if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
index 02434d8..0ace012 100644 (file)
@@ -65,10 +65,6 @@ struct diagnostic_context
   /* The number of times we have issued diagnostics.  */
   int diagnostic_count[DK_LAST_DIAGNOSTIC_KIND];
 
-  /* True if we should display the "warnings are being tread as error"
-     message, usually displayed once per compiler run.  */
-  bool some_warnings_are_errors;
-
   /* True if it has been requested that warnings be treated as errors.  */
   bool warning_as_error_requested;
 
index ad356ba..c63213c 100644 (file)
@@ -1217,12 +1217,12 @@ do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
      If one side isn't, we want a noncanonicalized comparison.  See PR
      middle-end/17564.  */
   if (HAVE_canonicalize_funcptr_for_compare
-      && TREE_CODE (TREE_TYPE (treeop0)) == POINTER_TYPE
-      && TREE_CODE (TREE_TYPE (TREE_TYPE (treeop0)))
-          == FUNCTION_TYPE
-      && TREE_CODE (TREE_TYPE (treeop1)) == POINTER_TYPE
-      && TREE_CODE (TREE_TYPE (TREE_TYPE (treeop1)))
-          == FUNCTION_TYPE)
+      && POINTER_TYPE_P (TREE_TYPE (treeop0))
+      && POINTER_TYPE_P (TREE_TYPE (treeop1))
+      && (TREE_CODE (TREE_TYPE (TREE_TYPE (treeop0))) == FUNCTION_TYPE
+         || TREE_CODE (TREE_TYPE (TREE_TYPE (treeop0))) == METHOD_TYPE)
+      && (TREE_CODE (TREE_TYPE (TREE_TYPE (treeop1))) == FUNCTION_TYPE
+         || TREE_CODE (TREE_TYPE (TREE_TYPE (treeop1))) == METHOD_TYPE))
     {
       rtx new_op0 = gen_reg_rtx (mode);
       rtx new_op1 = gen_reg_rtx (mode);
index 749d4ce..3614c10 100644 (file)
@@ -389,12 +389,14 @@ dump_struct_debug (tree type, enum debug_info_usage usage,
 #endif
 
 /* Get the number of HOST_WIDE_INTs needed to represent the precision
-   of the number.  */
+   of the number.  Some constants have a large uniform precision, so
+   we get the precision needed for the actual value of the number.  */
 
 static unsigned int
 get_full_len (const wide_int &op)
 {
-  return ((op.get_precision () + HOST_BITS_PER_WIDE_INT - 1)
+  int prec = wi::min_precision (op, UNSIGNED);
+  return ((prec + HOST_BITS_PER_WIDE_INT - 1)
          / HOST_BITS_PER_WIDE_INT);
 }
 
@@ -8901,14 +8903,14 @@ output_die (dw_die_ref die)
                {
                  dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
                                       "%s", name);
-                 name = NULL;
+                 name = "";
                }
            else
              for (i = 0; i < len; ++i)
                {
                  dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
                                       "%s", name);
-                 name = NULL;
+                 name = "";
                }
          }
          break;
@@ -15470,8 +15472,13 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
       return true;
 
     case CONST_WIDE_INT:
-      add_AT_wide (die, DW_AT_const_value,
-                  std::make_pair (rtl, GET_MODE (rtl)));
+      {
+       wide_int w1 = std::make_pair (rtl, MAX_MODE_INT);
+       unsigned int prec = MIN (wi::min_precision (w1, UNSIGNED),
+                                (unsigned int)CONST_WIDE_INT_NUNITS (rtl) * HOST_BITS_PER_WIDE_INT);
+       wide_int w = wi::zext (w1, prec);
+       add_AT_wide (die, DW_AT_const_value, w);
+      }
       return true;
 
     case CONST_DOUBLE:
index 483eacb..00ba64e 100644 (file)
@@ -6323,11 +6323,14 @@ need_atomic_barrier_p (enum memmodel model, bool pre)
     case MEMMODEL_CONSUME:
       return false;
     case MEMMODEL_RELEASE:
+    case MEMMODEL_SYNC_RELEASE:
       return pre;
     case MEMMODEL_ACQUIRE:
+    case MEMMODEL_SYNC_ACQUIRE:
       return !pre;
     case MEMMODEL_ACQ_REL:
     case MEMMODEL_SEQ_CST:
+    case MEMMODEL_SYNC_SEQ_CST:
       return true;
     default:
       gcc_unreachable ();
index 833ec21..a5246b5 100644 (file)
@@ -2235,7 +2235,7 @@ expand_builtin_eh_return (tree stackadj_tree ATTRIBUTE_UNUSED,
                     VOIDmode, EXPAND_NORMAL);
   tmp = convert_memory_address (Pmode, tmp);
   if (!crtl->eh.ehr_stackadj)
-    crtl->eh.ehr_stackadj = copy_to_reg (tmp);
+    crtl->eh.ehr_stackadj = copy_addr_to_reg (tmp);
   else if (tmp != crtl->eh.ehr_stackadj)
     emit_move_insn (crtl->eh.ehr_stackadj, tmp);
 #endif
@@ -2244,7 +2244,7 @@ expand_builtin_eh_return (tree stackadj_tree ATTRIBUTE_UNUSED,
                     VOIDmode, EXPAND_NORMAL);
   tmp = convert_memory_address (Pmode, tmp);
   if (!crtl->eh.ehr_handler)
-    crtl->eh.ehr_handler = copy_to_reg (tmp);
+    crtl->eh.ehr_handler = copy_addr_to_reg (tmp);
   else if (tmp != crtl->eh.ehr_handler)
     emit_move_insn (crtl->eh.ehr_handler, tmp);
 
index 6d085b1..029bcb6 100644 (file)
@@ -463,7 +463,9 @@ negate_expr_p (tree t)
 
     case PLUS_EXPR:
       if (HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
-         || HONOR_SIGNED_ZEROS (element_mode (type)))
+         || HONOR_SIGNED_ZEROS (element_mode (type))
+         || (INTEGRAL_TYPE_P (type)
+             && ! TYPE_OVERFLOW_WRAPS (type)))
        return false;
       /* -(A + B) -> (-B) - A.  */
       if (negate_expr_p (TREE_OPERAND (t, 1))
@@ -477,12 +479,23 @@ negate_expr_p (tree t)
       /* We can't turn -(A-B) into B-A when we honor signed zeros.  */
       return !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
             && !HONOR_SIGNED_ZEROS (element_mode (type))
+            && (! INTEGRAL_TYPE_P (type)
+                || TYPE_OVERFLOW_WRAPS (type))
             && reorder_operands_p (TREE_OPERAND (t, 0),
                                    TREE_OPERAND (t, 1));
 
     case MULT_EXPR:
-      if (TYPE_UNSIGNED (TREE_TYPE (t)))
-        break;
+      if (TYPE_UNSIGNED (type))
+       break;
+      /* INT_MIN/n * n doesn't overflow while negating one operand it does
+         if n is a power of two.  */
+      if (INTEGRAL_TYPE_P (TREE_TYPE (t))
+         && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (t))
+         && ! ((TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST
+                && ! integer_pow2p (TREE_OPERAND (t, 0)))
+               || (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
+                   && ! integer_pow2p (TREE_OPERAND (t, 1)))))
+       break;
 
       /* Fall through.  */
 
@@ -4925,8 +4938,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
       case GE_EXPR:
       case GT_EXPR:
        if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
-         arg1 = fold_convert_loc (loc, signed_type_for
-                              (TREE_TYPE (arg1)), arg1);
+         break;
        tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
        return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
       case UNLE_EXPR:
@@ -4936,8 +4948,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
       case LE_EXPR:
       case LT_EXPR:
        if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
-         arg1 = fold_convert_loc (loc, signed_type_for
-                              (TREE_TYPE (arg1)), arg1);
+         break;
        tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
        return negate_expr (fold_convert_loc (loc, type, tem));
       default:
@@ -6236,8 +6247,12 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
              && ((sign == UNSIGNED && tcode != MULT_EXPR) || sign == SIGNED))
            overflow_p = true;
          if (!overflow_p)
-           return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
-                               wide_int_to_tree (ctype, mul));
+           {
+             mul = wide_int::from (mul, TYPE_PRECISION (ctype),
+                                   TYPE_SIGN (TREE_TYPE (op1)));
+             return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
+                                 wide_int_to_tree (ctype, mul));
+           }
        }
 
       /* If these operations "cancel" each other, we have the main
@@ -7519,6 +7534,10 @@ native_encode_string (const_tree expr, unsigned char *ptr, int len, int off)
 int
 native_encode_expr (const_tree expr, unsigned char *ptr, int len, int off)
 {
+  /* We don't support starting at negative offset and -1 is special.  */
+  if (off < -1)
+    return 0;
+
   switch (TREE_CODE (expr))
     {
     case INTEGER_CST:
@@ -10376,25 +10395,32 @@ fold_binary_loc (location_t loc,
                {
                  tree tmp0 = var0;
                  tree tmp1 = var1;
+                 bool one_neg = false;
 
                  if (TREE_CODE (tmp0) == NEGATE_EXPR)
-                   tmp0 = TREE_OPERAND (tmp0, 0);
+                   {
+                     tmp0 = TREE_OPERAND (tmp0, 0);
+                     one_neg = !one_neg;
+                   }
                  if (CONVERT_EXPR_P (tmp0)
                      && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (tmp0, 0)))
                      && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (tmp0, 0)))
                          <= TYPE_PRECISION (atype)))
                    tmp0 = TREE_OPERAND (tmp0, 0);
                  if (TREE_CODE (tmp1) == NEGATE_EXPR)
-                   tmp1 = TREE_OPERAND (tmp1, 0);
+                   {
+                     tmp1 = TREE_OPERAND (tmp1, 0);
+                     one_neg = !one_neg;
+                   }
                  if (CONVERT_EXPR_P (tmp1)
                      && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (tmp1, 0)))
                      && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (tmp1, 0)))
                          <= TYPE_PRECISION (atype)))
                    tmp1 = TREE_OPERAND (tmp1, 0);
                  /* The only case we can still associate with two variables
-                    is if they are the same, modulo negation and bit-pattern
-                    preserving conversions.  */
-                 if (!operand_equal_p (tmp0, tmp1, 0))
+                    is if they cancel out.  */
+                 if (!one_neg
+                     || !operand_equal_p (tmp0, tmp1, 0))
                    ok = false;
                }
            }
index 2c3d142..5059cdf 100644 (file)
@@ -3500,9 +3500,11 @@ assign_parm_load_bounds (struct assign_parm_data_one *data,
 
 static void
 assign_bounds (vec<bounds_parm_data> &bndargs,
-              struct assign_parm_data_all &all)
+              struct assign_parm_data_all &all,
+              bool assign_regs, bool assign_special,
+              bool assign_bt)
 {
-  unsigned i, pass, handled = 0;
+  unsigned i, pass;
   bounds_parm_data *pbdata;
 
   if (!bndargs.exists ())
@@ -3516,17 +3518,20 @@ assign_bounds (vec<bounds_parm_data> &bndargs,
       {
        /* Pass 0 => regs only.  */
        if (pass == 0
-           && (!pbdata->parm_data.entry_parm
-               || GET_CODE (pbdata->parm_data.entry_parm) != REG))
+           && (!assign_regs
+               ||(!pbdata->parm_data.entry_parm
+                  || GET_CODE (pbdata->parm_data.entry_parm) != REG)))
          continue;
        /* Pass 1 => slots only.  */
        else if (pass == 1
-                && (!pbdata->parm_data.entry_parm
-                    || GET_CODE (pbdata->parm_data.entry_parm) == REG))
+                && (!assign_special
+                    || (!pbdata->parm_data.entry_parm
+                        || GET_CODE (pbdata->parm_data.entry_parm) == REG)))
          continue;
        /* Pass 2 => BT only.  */
        else if (pass == 2
-                && pbdata->parm_data.entry_parm)
+                && (!assign_bt
+                    || pbdata->parm_data.entry_parm))
          continue;
 
        if (!pbdata->parm_data.entry_parm
@@ -3547,14 +3552,7 @@ assign_bounds (vec<bounds_parm_data> &bndargs,
        else
          assign_parm_setup_stack (&all, pbdata->bounds_parm,
                                   &pbdata->parm_data);
-
-       /* Count handled bounds to make sure we miss nothing.  */
-       handled++;
       }
-
-  gcc_assert (handled == bndargs.length ());
-
-  bndargs.release ();
 }
 
 /* Assign RTL expressions to the function's parameters.  This may involve
@@ -3679,12 +3677,14 @@ assign_parms (tree fndecl)
              /* We expect this is the last parm.  Otherwise it is wrong
                 to assign bounds right now.  */
              gcc_assert (i == (fnargs.length () - 1));
-             assign_bounds (bndargs, all);
+             assign_bounds (bndargs, all, true, false, false);
              targetm.calls.setup_incoming_vararg_bounds (all.args_so_far,
                                                          data.promoted_mode,
                                                          data.passed_type,
                                                          &pretend_bytes,
                                                          false);
+             assign_bounds (bndargs, all, false, true, true);
+             bndargs.release ();
            }
        }
 
@@ -3696,7 +3696,8 @@ assign_parms (tree fndecl)
        bound_no++;
     }
 
-  assign_bounds (bndargs, all);
+  assign_bounds (bndargs, all, true, true, true);
+  bndargs.release ();
 
   if (targetm.calls.split_complex_arg)
     assign_parms_unsplit_complex (&all, fnargs);
@@ -5193,8 +5194,8 @@ diddle_return_value_1 (void (*doit) (rtx, void *), void *arg, rtx outgoing)
 void
 diddle_return_value (void (*doit) (rtx, void *), void *arg)
 {
-  diddle_return_value_1 (doit, arg, crtl->return_rtx);
   diddle_return_value_1 (doit, arg, crtl->return_bnd);
+  diddle_return_value_1 (doit, arg, crtl->return_rtx);
 }
 
 static void
index 560a371..8f94ff0 100644 (file)
@@ -1515,16 +1515,25 @@ capture_info::walk_match (operand *o, unsigned toplevel_arg,
 {
   if (capture *c = dyn_cast <capture *> (o))
     {
-      info[c->where].toplevel_msk |= 1 << toplevel_arg;
-      info[c->where].force_no_side_effects_p |= conditional_p;
-      info[c->where].cond_expr_cond_p |= cond_expr_cond_p;
-      /* Mark expr (non-leaf) captures and recurse.  */
+      unsigned where = c->where;
+      info[where].toplevel_msk |= 1 << toplevel_arg;
+      info[where].force_no_side_effects_p |= conditional_p;
+      info[where].cond_expr_cond_p |= cond_expr_cond_p;
+      if (!c->what)
+       return;
+      /* Recurse to exprs and captures.  */
+      if (is_a <capture *> (c->what)
+         || is_a <expr *> (c->what))
+       walk_match (c->what, toplevel_arg, conditional_p, false);
+      /* We need to look past multiple captures to find a captured
+        expression as with conditional converts two captures
+        can be collapsed onto the same expression.  */
+      while (c->what && is_a <capture *> (c->what))
+       c = as_a <capture *> (c->what);
+      /* Mark expr (non-leaf) captures.  */
       if (c->what
          && is_a <expr *> (c->what))
-       {
-         info[c->where].expr_p = true;
-         walk_match (c->what, toplevel_arg, conditional_p, false);
-       }
+       info[where].expr_p = true;
     }
   else if (expr *e = dyn_cast <expr *> (o))
     {
index 61ebc6c..78c50a9 100644 (file)
@@ -88,6 +88,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-match.h"
 #include "tree-phinodes.h"
 #include "ssa-iterators.h"
+#include "ipa-chkp.h"
 
 /* Return true when DECL can be referenced from current unit.
    FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -693,7 +694,7 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
              unlink_stmt_vdef (stmt);
              release_defs (stmt);
            }
-         gsi_replace (si_p, gimple_build_nop (), true);
+         gsi_replace (si_p, gimple_build_nop (), false);
          return;
        }
     }
@@ -734,7 +735,7 @@ replace_call_with_value (gimple_stmt_iterator *gsi, tree val)
       unlink_stmt_vdef (stmt);
       release_ssa_name (vdef);
     }
-  gsi_replace (gsi, repl, true);
+  gsi_replace (gsi, repl, false);
 }
 
 /* Replace the call at *GSI with the new call REPL and fold that
@@ -753,7 +754,7 @@ replace_call_with_call_and_fold (gimple_stmt_iterator *gsi, gimple repl)
       gimple_set_vuse (repl, gimple_vuse (stmt));
       SSA_NAME_DEF_STMT (gimple_vdef (repl)) = repl;
     }
-  gsi_replace (gsi, repl, true);
+  gsi_replace (gsi, repl, false);
   fold_stmt (gsi);
 }
 
@@ -800,7 +801,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
          unlink_stmt_vdef (stmt);
          release_ssa_name (vdef);
        }
-      gsi_replace (gsi, repl, true);
+      gsi_replace (gsi, repl, false);
       return true;
     }
 
@@ -813,7 +814,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
        release_ssa_name (gimple_vdef (stmt));
       if (!lhs)
        {
-         gsi_replace (gsi, gimple_build_nop (), true);
+         gsi_replace (gsi, gimple_build_nop (), false);
          return true;
        }
       goto done;
@@ -824,6 +825,18 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
       unsigned int src_align, dest_align;
       tree off0;
 
+      /* Inlining of memcpy/memmove may cause bounds lost (if we copy
+        pointers as wide integer) and also may result in huge function
+        size because of inlined bounds copy.  Thus don't inline for
+        functions we want to instrument.  */
+      if (flag_check_pointer_bounds
+         && chkp_instrumentable_p (cfun->decl)
+         /* Even if data may contain pointers we can inline if copy
+            less than a pointer size.  */
+         && (!tree_fits_uhwi_p (len)
+             || compare_tree_int (len, POINTER_SIZE_UNITS) >= 0))
+       return false;
+
       /* Build accesses at offset zero with a ref-all character type.  */
       off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
                                                         ptr_mode, true), 0);
@@ -895,7 +908,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
                        SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
                      if (!lhs)
                        {
-                         gsi_replace (gsi, new_stmt, true);
+                         gsi_replace (gsi, new_stmt, false);
                          return true;
                        }
                      gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
@@ -1175,7 +1188,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
        SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
       if (!lhs)
        {
-         gsi_replace (gsi, new_stmt, true);
+         gsi_replace (gsi, new_stmt, false);
          return true;
        }
       gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
@@ -1193,7 +1206,7 @@ done:
   dest = force_gimple_operand_gsi (gsi, dest, false, NULL_TREE, true,
                                   GSI_SAME_STMT);
   gimple repl = gimple_build_assign (lhs, dest);
-  gsi_replace (gsi, repl, true);
+  gsi_replace (gsi, repl, false);
   return true;
 }
 
@@ -1275,7 +1288,7 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
   if (gimple_call_lhs (stmt))
     {
       gimple asgn = gimple_build_assign (gimple_call_lhs (stmt), dest);
-      gsi_replace (gsi, asgn, true);
+      gsi_replace (gsi, asgn, false);
     }
   else
     {
@@ -2125,7 +2138,7 @@ gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi)
   gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
   gassign *ret = gimple_build_assign (gimple_call_lhs (stmt),
                                      POINTER_PLUS_EXPR, dest, tem);
-  gsi_replace (gsi, ret, true);
+  gsi_replace (gsi, ret, false);
   /* Finally fold the memcpy call.  */
   gimple_stmt_iterator gsi2 = *gsi;
   gsi_prev (&gsi2);
@@ -3207,7 +3220,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
                  && tree_int_cst_le (gimple_call_arg (stmt, 1),
                                      gimple_call_arg (stmt, 2))))
            {
-             gsi_replace (gsi, gimple_build_nop (), true);
+             gsi_replace (gsi, gimple_build_nop (), false);
              unlink_stmt_vdef (stmt);
              release_defs (stmt);
              return true;
index 7ae1330..90bb530 100644 (file)
@@ -361,7 +361,8 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
                return;
              }
            else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_POSIX_MEMALIGN
-                    && flag_tree_bit_ccp)
+                    && flag_tree_bit_ccp
+                    && gimple_builtin_call_types_compatible_p (stmt, decl))
              {
                lower_builtin_posix_memalign (gsi);
                return;
index e6dee07..db05c3d 100644 (file)
@@ -125,7 +125,14 @@ insert_trap_and_remove_trailing_statements (gimple_stmt_iterator *si_p, tree op)
   if (walk_stmt_load_store_ops (stmt, (void *)op,
                                check_loadstore,
                                check_loadstore))
-    gsi_insert_after (si_p, seq, GSI_NEW_STMT);
+    {
+      gsi_insert_after (si_p, seq, GSI_NEW_STMT);
+      if (stmt_ends_bb_p (stmt))
+       {
+         split_block (gimple_bb (stmt), stmt);
+         return;
+       }
+    }
   else
     gsi_insert_before (si_p, seq, GSI_NEW_STMT);
 
index e00de25..c85f83a 100644 (file)
@@ -6195,9 +6195,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
                    }
                  else
                    break;
-                 gcc_checking_assert (splay_tree_lookup (octx->variables,
-                                                         (splay_tree_key)
-                                                         decl) == NULL);
+                 if (splay_tree_lookup (octx->variables,
+                                        (splay_tree_key) decl) != NULL)
+                   {
+                     octx = NULL;
+                     break;
+                   }
                  flags = GOVD_SEEN;
                  if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
                    flags |= GOVD_FIRSTPRIVATE;
@@ -6979,7 +6982,7 @@ find_combined_omp_for (tree *tp, int *walk_subtrees, void *)
 static enum gimplify_status
 gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 {
-  tree for_stmt, orig_for_stmt, decl, var, t;
+  tree for_stmt, orig_for_stmt, inner_for_stmt = NULL_TREE, decl, var, t;
   enum gimplify_status ret = GS_ALL_DONE;
   enum gimplify_status tret;
   gomp_for *gfor;
@@ -7022,6 +7025,19 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
          }
     }
 
+  if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
+    {
+      gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP);
+      inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt),
+                                 find_combined_omp_for, NULL, NULL);
+      if (inner_for_stmt == NULL_TREE)
+       {
+         gcc_assert (seen_error ());
+         *expr_p = NULL_TREE;
+         return GS_ERROR;
+       }
+    }
+
   gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p,
                             simd ? ORT_SIMD : ORT_WORKSHARE);
   if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE)
@@ -7057,10 +7073,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 
   if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
     {
-      gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP);
-      for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt), find_combined_omp_for,
-                           NULL, NULL);
-      gcc_assert (for_stmt != NULL_TREE);
+      for_stmt = inner_for_stmt;
       gimplify_omp_ctxp->combined_loop = true;
     }
 
@@ -7104,13 +7117,27 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
                  OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
                  flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
                }
+             struct gimplify_omp_ctx *outer
+               = gimplify_omp_ctxp->outer_context;
+             if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
+               {
+                 if (outer->region_type == ORT_WORKSHARE
+                     && outer->combined_loop)
+                   {
+                     n = splay_tree_lookup (outer->variables,
+                                            (splay_tree_key)decl);
+                     if (n != NULL && (n->value & GOVD_LOCAL) != 0)
+                       {
+                         OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
+                         flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
+                       }
+                   }
+               }
+
              OMP_CLAUSE_DECL (c) = decl;
              OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
              OMP_FOR_CLAUSES (for_stmt) = c;
-             
              omp_add_variable (gimplify_omp_ctxp, decl, flags);
-             struct gimplify_omp_ctx *outer
-               = gimplify_omp_ctxp->outer_context;
              if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
                {
                  if (outer->region_type == ORT_WORKSHARE
@@ -7127,10 +7154,16 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
                    outer = NULL;
                  if (outer)
                    {
-                     omp_add_variable (outer, decl,
-                                       GOVD_LASTPRIVATE | GOVD_SEEN);
-                     if (outer->outer_context)
-                       omp_notice_variable (outer->outer_context, decl, true);
+                     n = splay_tree_lookup (outer->variables,
+                                            (splay_tree_key)decl);
+                     if (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0)
+                       {
+                         omp_add_variable (outer, decl,
+                                           GOVD_LASTPRIVATE | GOVD_SEEN);
+                         if (outer->outer_context)
+                           omp_notice_variable (outer->outer_context, decl,
+                                                true);
+                       }
                    }
                }
            }
@@ -7147,9 +7180,16 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
                  if (outer->region_type == ORT_WORKSHARE
                      && outer->combined_loop)
                    {
-                     if (outer->outer_context
-                         && (outer->outer_context->region_type
-                             == ORT_COMBINED_PARALLEL))
+                     n = splay_tree_lookup (outer->variables,
+                                            (splay_tree_key)decl);
+                     if (n != NULL && (n->value & GOVD_LOCAL) != 0)
+                       {
+                         lastprivate = false;
+                         outer = NULL;
+                       }
+                     else if (outer->outer_context
+                              && (outer->outer_context->region_type
+                                  == ORT_COMBINED_PARALLEL))
                        outer = outer->outer_context;
                      else if (omp_check_private (outer, decl, false))
                        outer = NULL;
@@ -7158,10 +7198,16 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
                    outer = NULL;
                  if (outer)
                    {
-                     omp_add_variable (outer, decl,
-                                       GOVD_LASTPRIVATE | GOVD_SEEN);
-                     if (outer->outer_context)
-                       omp_notice_variable (outer->outer_context, decl, true);
+                     n = splay_tree_lookup (outer->variables,
+                                            (splay_tree_key)decl);
+                     if (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0)
+                       {
+                         omp_add_variable (outer, decl,
+                                           GOVD_LASTPRIVATE | GOVD_SEEN);
+                         if (outer->outer_context)
+                           omp_notice_variable (outer->outer_context, decl,
+                                                true);
+                       }
                    }
                }
 
index dd3f03b..4557c9d 100644 (file)
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 
 #ifdef HAVE_isl
+#include <isl/constraint.h>
 #include <isl/set.h>
 #include <isl/map.h>
 #include <isl/union_map.h>
index edd357d..afde45f 100644 (file)
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 
 #ifdef HAVE_isl
+#include <isl/constraint.h>
 #include <isl/set.h>
 #include <isl/map.h>
 #include <isl/union_map.h>
@@ -227,7 +228,7 @@ scop_get_transformed_schedule (scop_p scop, vec<poly_bb_p> pbbs)
 /* Helper function used on each MAP of a isl_union_map.  Computes the
    maximal output dimension.  */
 
-static int
+static isl_stat
 max_number_of_out_dimensions (__isl_take isl_map *map, void *user)
 {
   int global_max = *((int *) user);
@@ -239,7 +240,7 @@ max_number_of_out_dimensions (__isl_take isl_map *map, void *user)
 
   isl_map_free (map);
   isl_space_free (space);
-  return 0;
+  return isl_stat_ok;
 }
 
 /* Extends the output dimension of MAP to MAX dimensions.  */
@@ -263,12 +264,12 @@ struct extend_schedule_str {
 
 /* Helper function for extend_schedule.  */
 
-static int
+static isl_stat
 extend_schedule_1 (__isl_take isl_map *map, void *user)
 {
   struct extend_schedule_str *str = (struct extend_schedule_str *) user;
   str->umap = isl_union_map_add_map (str->umap, extend_map (map, str->max));
-  return 0;
+  return isl_stat_ok;
 }
 
 /* Return a relation that has uniform output dimensions.  */
@@ -277,16 +278,16 @@ __isl_give isl_union_map *
 extend_schedule (__isl_take isl_union_map *x)
 {
   int max = 0;
-  int res;
+  isl_stat res;
   struct extend_schedule_str str;
 
   res = isl_union_map_foreach_map (x, max_number_of_out_dimensions, (void *) &max);
-  gcc_assert (res == 0);
+  gcc_assert (res == isl_stat_ok);
 
   str.max = max;
   str.umap = isl_union_map_empty (isl_union_map_get_space (x));
   res = isl_union_map_foreach_map (x, extend_schedule_1, (void *) &str);
-  gcc_assert (res == 0);
+  gcc_assert (res == isl_stat_ok);
 
   isl_union_map_free (x);
   return str.umap;
index 8c0d95d..2750ddf 100644 (file)
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 
 #ifdef HAVE_isl
+#include <isl/constraint.h>
 #include <isl/aff.h>
 #include <isl/set.h>
 #include <isl/map.h>
index 90ce0c6..a83a85d 100644 (file)
@@ -21,7 +21,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 
 #ifdef HAVE_isl
+#include <isl/constraint.h>
 #include <isl/set.h>
+#include <isl/union_set.h>
 #include <isl/map.h>
 #include <isl/union_map.h>
 #include <isl/ast_build.h>
index 8bdf744..e0c566b 100644 (file)
@@ -21,7 +21,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 
 #ifdef HAVE_isl
+#include <isl/constraint.h>
 #include <isl/set.h>
+#include <isl/union_set.h>
 #include <isl/map.h>
 #include <isl/union_map.h>
 #include <isl/schedule.h>
@@ -530,13 +532,13 @@ getScheduleMap (isl_schedule *Schedule, isl_union_map **map_sepcl)
   return ScheduleMap;
 }
 
-static int
+static isl_stat
 getSingleMap (__isl_take isl_map *map, void *user)
 {
   isl_map **singleMap = (isl_map **) user;
   *singleMap = map;
 
-  return 0;
+  return isl_stat_ok;
 }
 
 static void
@@ -608,7 +610,11 @@ optimize_isl (scop_p scop)
 
   isl_options_set_schedule_max_constant_term (scop->ctx, CONSTANT_BOUND);
   isl_options_set_schedule_maximize_band_depth (scop->ctx, 1);
+#ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
+  isl_options_set_schedule_serialize_sccs (scop->ctx, 1);
+#else
   isl_options_set_schedule_fuse (scop->ctx, ISL_SCHEDULE_FUSE_MIN);
+#endif
   isl_options_set_on_error (scop->ctx, ISL_ON_ERROR_CONTINUE);
 
 #ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE
index ae90c29..c5287d2 100644 (file)
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 
 #ifdef HAVE_isl
+#include <isl/constraint.h>
 #include <isl/set.h>
 #include <isl/map.h>
 #include <isl/union_map.h>
index afc0121..aa7b07c 100644 (file)
@@ -22,6 +22,11 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_GRAPHITE_POLY_H
 #define GCC_GRAPHITE_POLY_H
 
+#ifndef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
+# define isl_stat int
+# define isl_stat_ok 0
+#endif
+
 typedef struct poly_dr *poly_dr_p;
 
 typedef struct poly_bb *poly_bb_p;
index 4512fe7..522213f 100644 (file)
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 
 #ifdef HAVE_isl
+#include <isl/constraint.h>
 #include <isl/set.h>
 #include <isl/map.h>
 #include <isl/union_map.h>
index 23b63ad..4230f62 100644 (file)
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 
 #ifdef HAVE_isl
+#include <isl/constraint.h>
 #include <isl/set.h>
 #include <isl/map.h>
 #include <isl/union_map.h>
@@ -2634,9 +2635,17 @@ is_reduction_operation_p (gimple stmt)
   gcc_assert (is_gimple_assign (stmt));
   code = gimple_assign_rhs_code (stmt);
 
-  return flag_associative_math
-    && commutative_tree_code (code)
-    && associative_tree_code (code);
+  if (!commutative_tree_code (code)
+      || !associative_tree_code (code))
+    return false;
+
+  tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+
+  if (FLOAT_TYPE_P (type))
+    return flag_associative_math;
+
+  return (INTEGRAL_TYPE_P (type)
+         && TYPE_OVERFLOW_WRAPS (type));
 }
 
 /* Returns true when PHI contains an argument ARG.  */
index c8f0617..a0cf455 100644 (file)
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 
 #ifdef HAVE_isl
+#include <isl/constraint.h>
 #include <isl/set.h>
 #include <isl/map.h>
 #include <isl/options.h>
index a3e3e5c..db07889 100644 (file)
@@ -2150,12 +2150,49 @@ noce_try_abs (struct noce_if_info *if_info)
 
   /* Work around funny ideas get_condition has wrt canonicalization.
      Note that these rtx constants are known to be CONST_INT, and
-     therefore imply integer comparisons.  */
+     therefore imply integer comparisons.
+     The one_cmpl case is more complicated, as we want to handle
+     only x < 0 ? ~x : x or x >= 0 ? ~x : x but not
+     x <= 0 ? ~x : x or x > 0 ? ~x : x, as the latter two
+     have different result for x == 0.  */
   if (c == constm1_rtx && GET_CODE (cond) == GT)
-    ;
+    {
+      if (one_cmpl && negate)
+       return FALSE;
+    }
   else if (c == const1_rtx && GET_CODE (cond) == LT)
-    ;
-  else if (c != CONST0_RTX (GET_MODE (b)))
+    {
+      if (one_cmpl && !negate)
+       return FALSE;
+    }
+  else if (c == CONST0_RTX (GET_MODE (b)))
+    {
+      if (one_cmpl)
+       switch (GET_CODE (cond))
+         {
+         case GT:
+           if (!negate)
+             return FALSE;
+           break;
+         case GE:
+           /* >= 0 is the same case as above > -1.  */
+           if (negate)
+             return FALSE;
+           break;
+         case LT:
+           if (negate)
+             return FALSE;
+           break;
+         case LE:
+           /* <= 0 is the same case as above < 1.  */
+           if (!negate)
+             return FALSE;
+           break;
+         default:
+           return FALSE;
+         }
+    }
+  else
     return FALSE;
 
   /* Determine what sort of operation this is.  */
index 70e629b..d3f0863 100644 (file)
@@ -104,7 +104,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Return 1 calls to FNDECL should be replaced with
    a call to wrapper function.  */
-static bool
+bool
 chkp_wrap_function (tree fndecl)
 {
   if (!flag_chkp_use_wrappers)
@@ -139,6 +139,51 @@ chkp_wrap_function (tree fndecl)
   return false;
 }
 
+static const char *
+chkp_wrap_function_name (tree fndecl)
+{
+  gcc_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
+
+  switch (DECL_FUNCTION_CODE (fndecl))
+    {
+    case BUILT_IN_STRLEN:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "strlen";
+    case BUILT_IN_STRCPY:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "strcpy";
+    case BUILT_IN_STRNCPY:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "strncpy";
+    case BUILT_IN_STPCPY:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "stpcpy";
+    case BUILT_IN_STPNCPY:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "stpncpy";
+    case BUILT_IN_STRCAT:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "strcat";
+    case BUILT_IN_STRNCAT:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "strncat";
+    case BUILT_IN_MEMCPY:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "memcpy";
+    case BUILT_IN_MEMPCPY:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "mempcpy";
+    case BUILT_IN_MEMSET:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "memset";
+    case BUILT_IN_MEMMOVE:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "memmove";
+    case BUILT_IN_BZERO:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "bzero";
+    case BUILT_IN_MALLOC:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "malloc";
+    case BUILT_IN_CALLOC:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "calloc";
+    case BUILT_IN_REALLOC:
+      return CHKP_WRAPPER_SYMBOL_PREFIX "realloc";
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return "";
+}
+
 /* Build a clone of FNDECL with a modified name.  */
 
 static tree
@@ -164,9 +209,8 @@ chkp_build_instrumented_fndecl (tree fndecl)
      instrumented version.  */
   if (chkp_wrap_function(fndecl))
     {
-      s = CHKP_WRAPPER_SYMBOL_PREFIX;
-      s += IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
-      new_name = get_identifier (s.c_str ());
+      new_name = get_identifier (chkp_wrap_function_name (fndecl));
+      DECL_VISIBILITY (new_decl) = VISIBILITY_DEFAULT;
     }
   else
     {
@@ -541,25 +585,10 @@ chkp_maybe_create_clone (tree fndecl)
 
       if (gimple_has_body_p (fndecl))
        {
-         /* If function will not be instrumented, then it's instrumented
-            version is a thunk for the original.  */
-         if (!chkp_instrumentable_p (fndecl))
-           {
-             clone->remove_callees ();
-             clone->remove_all_references ();
-             clone->thunk.thunk_p = true;
-             clone->thunk.add_pointer_bounds_args = true;
-             clone->create_edge (node, NULL, 0, CGRAPH_FREQ_BASE);
-             /* Thunk shouldn't be a cdtor.  */
-             DECL_STATIC_CONSTRUCTOR (clone->decl) = 0;
-             DECL_STATIC_DESTRUCTOR (clone->decl) = 0;
-           }
-         else
-           {
-             tree_function_versioning (fndecl, new_decl, NULL, false,
-                                       NULL, false, NULL, NULL);
-             clone->lowered = true;
-           }
+         gcc_assert (chkp_instrumentable_p (fndecl));
+         tree_function_versioning (fndecl, new_decl, NULL, false,
+                                   NULL, false, NULL, NULL);
+         clone->lowered = true;
        }
 
       /* New params are inserted after versioning because it
@@ -586,12 +615,7 @@ chkp_maybe_create_clone (tree fndecl)
 
       /* Clone all aliases.  */
       for (i = 0; node->iterate_direct_aliases (i, ref); i++)
-       {
-         struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
-         struct cgraph_node *chkp_alias
-           = chkp_maybe_create_clone (alias->decl);
-         chkp_alias->create_reference (clone, IPA_REF_ALIAS, NULL);
-       }
+       chkp_maybe_create_clone (ref->referring->decl);
 
       /* Clone all thunks.  */
       for (e = node->callers; e; e = e->next_caller)
@@ -615,7 +639,10 @@ chkp_maybe_create_clone (tree fndecl)
 
          ref = node->ref_list.first_reference ();
          if (ref)
-           chkp_maybe_create_clone (ref->referred->decl);
+           {
+             target = chkp_maybe_create_clone (ref->referred->decl);
+             clone->create_reference (target, IPA_REF_ALIAS);
+           }
 
          if (node->alias_target)
            {
index 6708fe9..547487e 100644 (file)
@@ -24,5 +24,6 @@ extern tree chkp_copy_function_type_adding_bounds (tree orig_type);
 extern tree chkp_maybe_clone_builtin_fndecl (tree fndecl);
 extern cgraph_node *chkp_maybe_create_clone (tree fndecl);
 extern bool chkp_instrumentable_p (tree fndecl);
+extern bool chkp_wrap_function (tree fndecl);
 
 #endif /* GCC_IPA_CHKP_H */
index 6969f5a..e319785 100644 (file)
@@ -483,7 +483,7 @@ types_same_for_odr (const_tree type1, const_tree type2, bool strict)
        return false;
       if (TREE_CODE (type1) == RECORD_TYPE
          && (TYPE_BINFO (type1) == NULL_TREE)
-             != (TYPE_BINFO (type1) == NULL_TREE))
+             != (TYPE_BINFO (type2) == NULL_TREE))
        return false;
       if (TREE_CODE (type1) == RECORD_TYPE && TYPE_BINFO (type1)
          && (BINFO_VTABLE (TYPE_BINFO (type1)) == NULL_TREE)
index b902373..3f29011 100644 (file)
@@ -273,7 +273,6 @@ sem_item::target_supports_symbol_aliases_p (void)
 sem_function::sem_function (bitmap_obstack *stack): sem_item (FUNC, stack),
   m_checker (NULL), m_compared_func (NULL)
 {
-  arg_types.create (0);
   bb_sizes.create (0);
   bb_sorted.create (0);
 }
@@ -285,7 +284,6 @@ sem_function::sem_function (cgraph_node *node, hashval_t hash,
   sem_item (FUNC, node, hash, stack),
   m_checker (NULL), m_compared_func (NULL)
 {
-  arg_types.create (0);
   bb_sizes.create (0);
   bb_sorted.create (0);
 }
@@ -295,7 +293,6 @@ sem_function::~sem_function ()
   for (unsigned i = 0; i < bb_sorted.length (); i++)
     delete (bb_sorted[i]);
 
-  arg_types.release ();
   bb_sizes.release ();
   bb_sorted.release ();
 }
@@ -417,6 +414,47 @@ bool sem_function::compare_edge_flags (cgraph_edge *e1, cgraph_edge *e2)
   return true;
 }
 
+/* Perform additional check needed to match types function parameters that are
+   used.  Unlike for normal decls it matters if type is TYPE_RESTRICT and we
+   make an assumption that REFERENCE_TYPE parameters are always non-NULL.  */
+
+bool
+sem_function::compatible_parm_types_p (tree parm1, tree parm2)
+{
+  /* Be sure that parameters are TBAA compatible.  */
+  if (!func_checker::compatible_types_p (parm1, parm2))
+    return return_false_with_msg ("parameter type is not compatible");
+
+  if (POINTER_TYPE_P (parm1)
+      && (TYPE_RESTRICT (parm1) != TYPE_RESTRICT (parm2)))
+    return return_false_with_msg ("argument restrict flag mismatch");
+
+  /* nonnull_arg_p implies non-zero range to REFERENCE types.  */
+  if (POINTER_TYPE_P (parm1)
+      && TREE_CODE (parm1) != TREE_CODE (parm2)
+      && opt_for_fn (decl, flag_delete_null_pointer_checks))
+    return return_false_with_msg ("pointer wrt reference mismatch");
+
+  return true;
+}
+
+/* Return true if parameter I may be used.  */
+
+bool
+sem_function::param_used_p (unsigned int i)
+{
+  if (ipa_node_params_sum == NULL)
+    return false;
+
+  struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ());
+
+  if (parms_info->descriptors.is_empty ()
+      || parms_info->descriptors.length () <= i)
+     return true;
+
+  return ipa_is_param_used (IPA_NODE_REF (get_node ()), i);
+}
+
 /* Fast equality function based on knowledge known in WPA.  */
 
 bool
@@ -427,9 +465,6 @@ sem_function::equals_wpa (sem_item *item,
 
   m_compared_func = static_cast<sem_function *> (item);
 
-  if (arg_types.length () != m_compared_func->arg_types.length ())
-    return return_false_with_msg ("different number of arguments");
-
   /* Compare special function DECL attributes.  */
   if (DECL_FUNCTION_PERSONALITY (decl)
       != DECL_FUNCTION_PERSONALITY (item->decl))
@@ -506,26 +541,40 @@ sem_function::equals_wpa (sem_item *item,
     }
 
   /* Result type checking.  */
-  if (!func_checker::compatible_types_p (result_type,
-                                        m_compared_func->result_type))
+  if (!func_checker::compatible_types_p
+        (TREE_TYPE (TREE_TYPE (decl)),
+         TREE_TYPE (TREE_TYPE (m_compared_func->decl))))
     return return_false_with_msg ("result types are different");
 
   /* Checking types of arguments.  */
-  for (unsigned i = 0; i < arg_types.length (); i++)
+  tree list1 = TYPE_ARG_TYPES (TREE_TYPE (decl)),
+       list2 = TYPE_ARG_TYPES (TREE_TYPE (m_compared_func->decl));
+  for (unsigned i = 0; list1 && list2;
+       list1 = TREE_CHAIN (list1), list2 = TREE_CHAIN (list2), i++)
     {
+      tree parm1 = TREE_VALUE (list1);
+      tree parm2 = TREE_VALUE (list2);
+
       /* This guard is here for function pointer with attributes (pr59927.c).  */
-      if (!arg_types[i] || !m_compared_func->arg_types[i])
+      if (!parm1 || !parm2)
        return return_false_with_msg ("NULL argument type");
 
-      if (!func_checker::compatible_types_p (arg_types[i],
-                                            m_compared_func->arg_types[i]))
-       return return_false_with_msg ("argument type is different");
-      if (POINTER_TYPE_P (arg_types[i])
-         && (TYPE_RESTRICT (arg_types[i])
-             != TYPE_RESTRICT (m_compared_func->arg_types[i])))
-       return return_false_with_msg ("argument restrict flag mismatch");
+      /* Verify that types are compatible to ensure that both functions
+        have same calling conventions.  */
+      if (!types_compatible_p (parm1, parm2))
+       return return_false_with_msg ("parameter types are not compatible");
+
+      if (!param_used_p (i))
+       continue;
+
+      /* Perform additional checks for used parameters.  */
+      if (!compatible_parm_types_p (parm1, parm2))
+       return false;
     }
 
+  if (list1 || list2)
+    return return_false_with_msg ("Mismatched number of parameters");
+
   if (node->num_references () != item->node->num_references ())
     return return_false_with_msg ("different number of references");
 
@@ -740,11 +789,23 @@ sem_function::equals_private (sem_item *item,
   if (decl1 != decl2)
     return return_false();
 
-  for (arg1 = DECL_ARGUMENTS (decl),
-       arg2 = DECL_ARGUMENTS (m_compared_func->decl);
-       arg1; arg1 = DECL_CHAIN (arg1), arg2 = DECL_CHAIN (arg2))
-    if (!m_checker->compare_decl (arg1, arg2))
-      return return_false ();
+  arg1 = DECL_ARGUMENTS (decl);
+  arg2 = DECL_ARGUMENTS (m_compared_func->decl);
+  for (unsigned i = 0;
+       arg1 && arg2; arg1 = DECL_CHAIN (arg1), arg2 = DECL_CHAIN (arg2), i++)
+    {
+      if (!types_compatible_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
+       return return_false_with_msg ("argument types are not compatible");
+      if (!param_used_p (i))
+       continue;
+      /* Perform additional checks for used parameters.  */
+      if (!compatible_parm_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
+       return false;
+      if (!m_checker->compare_decl (arg1, arg2))
+       return return_false ();
+    }
+  if (arg1 || arg2)
+    return return_false_with_msg ("Mismatched number of arguments");
 
   /* Fill-up label dictionary.  */
   for (unsigned i = 0; i < bb_sorted.length (); ++i)
@@ -1222,8 +1283,6 @@ sem_function::init (void)
 
     bb_sorted.safe_push (semantic_bb);
   }
-
-  parse_tree_args ();
 }
 
 /* Accumulate to HSTATE a hash of expression EXP.
@@ -1476,37 +1535,6 @@ sem_function::parse (cgraph_node *node, bitmap_obstack *stack)
   return f;
 }
 
-/* Parses function arguments and result type.  */
-
-void
-sem_function::parse_tree_args (void)
-{
-  tree result;
-
-  if (arg_types.exists ())
-    arg_types.release ();
-
-  arg_types.create (4);
-  tree fnargs = DECL_ARGUMENTS (decl);
-
-  for (tree parm = fnargs; parm; parm = DECL_CHAIN (parm))
-    arg_types.safe_push (DECL_ARG_TYPE (parm));
-
-  /* Function result type.  */
-  result = DECL_RESULT (decl);
-  result_type = result ? TREE_TYPE (result) : NULL;
-
-  /* During WPA, we can get arguments by following method.  */
-  if (!fnargs)
-    {
-      tree type = TYPE_ARG_TYPES (TREE_TYPE (decl));
-      for (tree parm = type; parm; parm = TREE_CHAIN (parm))
-       arg_types.safe_push (TYPE_CANONICAL (TREE_VALUE (parm)));
-
-      result_type = TREE_TYPE (TREE_TYPE (decl));
-    }
-}
-
 /* For given basic blocks BB1 and BB2 (from functions FUNC1 and FUNC),
    return true if phi nodes are semantically equivalent in these blocks .  */
 
index 7eb9f27..98a3d4a 100644 (file)
@@ -276,7 +276,6 @@ public:
 
   inline virtual void init_wpa (void)
   {
-    parse_tree_args ();
   }
 
   virtual void init (void);
@@ -294,9 +293,6 @@ public:
     dump_function_to_file (decl, file, TDF_DETAILS);
   }
 
-  /* Parses function arguments and result type.  */
-  void parse_tree_args (void);
-
   /* Returns cgraph_node.  */
   inline cgraph_node *get_node (void)
   {
@@ -313,15 +309,13 @@ public:
      semantic function item.  */
   static sem_function *parse (cgraph_node *node, bitmap_obstack *stack);
 
+  /* Perform additional checks needed to match types of used function
+     paramters.  */
+  bool compatible_parm_types_p (tree, tree);
+
   /* Exception handling region tree.  */
   eh_region region_tree;
 
-  /* Result type tree node.  */
-  tree result_type;
-
-  /* Array of argument tree types.  */
-  vec <tree> arg_types;
-
   /* Number of function arguments.  */
   unsigned int arg_count;
 
@@ -343,6 +337,9 @@ public:
   /* Array of structures for all basic blocks.  */
   vec <ipa_icf_gimple::sem_bb *> bb_sorted;
 
+  /* Return true if parameter I may be used.  */
+  bool param_used_p (unsigned int i);
+
 private:
   /* Calculates hash value based on a BASIC_BLOCK.  */
   hashval_t get_bb_hash (const ipa_icf_gimple::sem_bb *basic_block);
index 5d99887..54b6abe 100644 (file)
@@ -1602,7 +1602,7 @@ unmodified_parm (gimple stmt, tree op)
    loaded.  */
 
 static bool
-unmodified_parm_or_parm_agg_item (struct ipa_node_params *info,
+unmodified_parm_or_parm_agg_item (struct ipa_func_body_info *fbi,
                                  gimple stmt, tree op, int *index_p,
                                  struct agg_position_info *aggpos)
 {
@@ -1611,7 +1611,7 @@ unmodified_parm_or_parm_agg_item (struct ipa_node_params *info,
   gcc_checking_assert (aggpos);
   if (res)
     {
-      *index_p = ipa_get_param_decl_index (info, res);
+      *index_p = ipa_get_param_decl_index (fbi->info, res);
       if (*index_p < 0)
        return false;
       aggpos->agg_contents = false;
@@ -1627,13 +1627,14 @@ unmodified_parm_or_parm_agg_item (struct ipa_node_params *info,
       stmt = SSA_NAME_DEF_STMT (op);
       op = gimple_assign_rhs1 (stmt);
       if (!REFERENCE_CLASS_P (op))
-       return unmodified_parm_or_parm_agg_item (info, stmt, op, index_p,
+       return unmodified_parm_or_parm_agg_item (fbi, stmt, op, index_p,
                                                 aggpos);
     }
 
   aggpos->agg_contents = true;
-  return ipa_load_from_parm_agg (info, stmt, op, index_p, &aggpos->offset,
-                                &aggpos->by_ref);
+  return ipa_load_from_parm_agg (fbi, fbi->info->descriptors,
+                                stmt, op, index_p, &aggpos->offset,
+                                NULL, &aggpos->by_ref);
 }
 
 /* See if statement might disappear after inlining.
@@ -1772,7 +1773,7 @@ eliminated_by_inlining_prob (gimple stmt)
    predicates to the CFG edges.   */
 
 static void
-set_cond_stmt_execution_predicate (struct ipa_node_params *info,
+set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
                                   struct inline_summary *summary,
                                   basic_block bb)
 {
@@ -1795,7 +1796,7 @@ set_cond_stmt_execution_predicate (struct ipa_node_params *info,
   /* TODO: handle conditionals like
      var = op0 < 4;
      if (var != 0).  */
-  if (unmodified_parm_or_parm_agg_item (info, last, op, &index, &aggpos))
+  if (unmodified_parm_or_parm_agg_item (fbi, last, op, &index, &aggpos))
     {
       code = gimple_cond_code (last);
       inverted_code = invert_tree_comparison (code, HONOR_NANS (op));
@@ -1838,8 +1839,7 @@ set_cond_stmt_execution_predicate (struct ipa_node_params *info,
       || gimple_call_num_args (set_stmt) != 1)
     return;
   op2 = gimple_call_arg (set_stmt, 0);
-  if (!unmodified_parm_or_parm_agg_item
-      (info, set_stmt, op2, &index, &aggpos))
+  if (!unmodified_parm_or_parm_agg_item (fbi, set_stmt, op2, &index, &aggpos))
     return;
   FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALSE_VALUE)
     {
@@ -1855,7 +1855,7 @@ set_cond_stmt_execution_predicate (struct ipa_node_params *info,
    predicates to the CFG edges.   */
 
 static void
-set_switch_stmt_execution_predicate (struct ipa_node_params *info,
+set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
                                     struct inline_summary *summary,
                                     basic_block bb)
 {
@@ -1873,7 +1873,7 @@ set_switch_stmt_execution_predicate (struct ipa_node_params *info,
     return;
   gswitch *last = as_a <gswitch *> (lastg);
   op = gimple_switch_index (last);
-  if (!unmodified_parm_or_parm_agg_item (info, last, op, &index, &aggpos))
+  if (!unmodified_parm_or_parm_agg_item (fbi, last, op, &index, &aggpos))
     return;
 
   FOR_EACH_EDGE (e, ei, bb->succs)
@@ -1916,8 +1916,8 @@ set_switch_stmt_execution_predicate (struct ipa_node_params *info,
    which it is executable.  */
 
 static void
-compute_bb_predicates (struct cgraph_node *node,
-                      struct ipa_node_params *parms_info,
+compute_bb_predicates (struct ipa_func_body_info *fbi,
+                      struct cgraph_node *node,
                       struct inline_summary *summary)
 {
   struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
@@ -1926,8 +1926,8 @@ compute_bb_predicates (struct cgraph_node *node,
 
   FOR_EACH_BB_FN (bb, my_function)
     {
-      set_cond_stmt_execution_predicate (parms_info, summary, bb);
-      set_switch_stmt_execution_predicate (parms_info, summary, bb);
+      set_cond_stmt_execution_predicate (fbi, summary, bb);
+      set_switch_stmt_execution_predicate (fbi, summary, bb);
     }
 
   /* Entry block is always executable.  */
@@ -2059,7 +2059,7 @@ will_be_nonconstant_expr_predicate (struct ipa_node_params *info,
    a compile time constant.  */
 
 static struct predicate
-will_be_nonconstant_predicate (struct ipa_node_params *info,
+will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
                               struct inline_summary *summary,
                               gimple stmt,
                               vec<predicate_t> nonconstant_names)
@@ -2093,7 +2093,7 @@ will_be_nonconstant_predicate (struct ipa_node_params *info,
       tree op;
       gcc_assert (gimple_assign_single_p (stmt));
       op = gimple_assign_rhs1 (stmt);
-      if (!unmodified_parm_or_parm_agg_item (info, stmt, op, &base_index,
+      if (!unmodified_parm_or_parm_agg_item (fbi, stmt, op, &base_index,
                                             &aggpos))
        return p;
     }
@@ -2106,7 +2106,7 @@ will_be_nonconstant_predicate (struct ipa_node_params *info,
     {
       tree parm = unmodified_parm (stmt, use);
       /* For arguments we can build a condition.  */
-      if (parm && ipa_get_param_decl_index (info, parm) >= 0)
+      if (parm && ipa_get_param_decl_index (fbi->info, parm) >= 0)
        continue;
       if (TREE_CODE (use) != SSA_NAME)
        return p;
@@ -2127,7 +2127,7 @@ will_be_nonconstant_predicate (struct ipa_node_params *info,
       tree parm = unmodified_parm (stmt, use);
       int index;
 
-      if (parm && (index = ipa_get_param_decl_index (info, parm)) >= 0)
+      if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0)
        {
          if (index != base_index)
            p = add_condition (summary, index, NULL, CHANGED, NULL_TREE);
@@ -2509,13 +2509,17 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
   int freq;
   struct inline_summary *info = inline_summaries->get (node);
   struct predicate bb_predicate;
-  struct ipa_node_params *parms_info = NULL;
+  struct ipa_func_body_info fbi;
   vec<predicate_t> nonconstant_names = vNULL;
   int nblocks, n;
   int *order;
   predicate array_index = true_predicate ();
   gimple fix_builtin_expect_stmt;
 
+  gcc_assert (my_function && my_function->cfg);
+  gcc_assert (cfun == my_function);
+
+  memset(&fbi, 0, sizeof(fbi));
   info->conds = NULL;
   info->entry = NULL;
 
@@ -2538,7 +2542,11 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
 
       if (ipa_node_params_sum)
        {
-         parms_info = IPA_NODE_REF (node);
+         fbi.node = node;
+         fbi.info = IPA_NODE_REF (node);
+         fbi.bb_infos = vNULL;
+         fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun));
+         fbi.param_count = count_formal_params(node->decl);
          nonconstant_names.safe_grow_cleared
            (SSANAMES (my_function)->length ());
        }
@@ -2556,10 +2564,8 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
   bb_predicate = not_inlined_predicate ();
   account_size_time (info, 2 * INLINE_SIZE_SCALE, 0, &bb_predicate);
 
-  gcc_assert (my_function && my_function->cfg);
-  if (parms_info)
-    compute_bb_predicates (node, parms_info, info);
-  gcc_assert (cfun == my_function);
+  if (fbi.info)
+    compute_bb_predicates (&fbi, node, info);
   order = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
   nblocks = pre_and_rev_post_order_compute (NULL, order, false);
   for (n = 0; n < nblocks; n++)
@@ -2576,7 +2582,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
        }
 
       /* TODO: Obviously predicates can be propagated down across CFG.  */
-      if (parms_info)
+      if (fbi.info)
        {
          if (bb->aux)
            bb_predicate = *(struct predicate *) bb->aux;
@@ -2592,7 +2598,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
          dump_predicate (dump_file, info->conds, &bb_predicate);
        }
 
-      if (parms_info && nonconstant_names.exists ())
+      if (fbi.info && nonconstant_names.exists ())
        {
          struct predicate phi_predicate;
          bool first_phi = true;
@@ -2601,7 +2607,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
               gsi_next (&bsi))
            {
              if (first_phi
-                 && !phi_result_unknown_predicate (parms_info, info, bb,
+                 && !phi_result_unknown_predicate (fbi.info, info, bb,
                                                    &phi_predicate,
                                                    nonconstant_names))
                break;
@@ -2710,9 +2716,9 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
          /* TODO: When conditional jump or swithc is known to be constant, but
             we did not translate it into the predicates, we really can account
             just maximum of the possible paths.  */
-         if (parms_info)
+         if (fbi.info)
            will_be_nonconstant
-             = will_be_nonconstant_predicate (parms_info, info,
+             = will_be_nonconstant_predicate (&fbi, info,
                                               stmt, nonconstant_names);
          if (this_time || this_size)
            {
@@ -2727,7 +2733,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
              if (prob == 2 && dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "\t\tWill be eliminated by inlining\n");
 
-             if (parms_info)
+             if (fbi.info)
                p = and_predicates (info->conds, &bb_predicate,
                                    &will_be_nonconstant);
              else
@@ -2784,9 +2790,8 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
        {
          vec<edge> exits;
          edge ex;
-         unsigned int j, i;
+         unsigned int j;
          struct tree_niter_desc niter_desc;
-         basic_block *body = get_loop_body (loop);
          bb_predicate = *(struct predicate *) loop->header->aux;
 
          exits = get_loop_exit_edges (loop);
@@ -2795,7 +2800,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
                && !is_gimple_min_invariant (niter_desc.niter))
            {
              predicate will_be_nonconstant
-               = will_be_nonconstant_expr_predicate (parms_info, info,
+               = will_be_nonconstant_expr_predicate (fbi.info, info,
                                                      niter_desc.niter,
                                                      nonconstant_names);
              if (!true_predicate_p (&will_be_nonconstant))
@@ -2812,46 +2817,32 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
            }
          exits.release ();
 
-         for (i = 0; i < loop->num_nodes; i++)
+         for (gphi_iterator gsi = gsi_start_phis (loop->header);
+              !gsi_end_p (gsi); gsi_next (&gsi))
            {
-             gimple_stmt_iterator gsi;
-             bb_predicate = *(struct predicate *) body[i]->aux;
-             for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi);
-                  gsi_next (&gsi))
-               {
-                 gimple stmt = gsi_stmt (gsi);
-                 affine_iv iv;
-                 ssa_op_iter iter;
-                 tree use;
-
-                 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
-                 {
-                   predicate will_be_nonconstant;
-
-                   if (!simple_iv
-                       (loop, loop_containing_stmt (stmt), use, &iv, true)
-                       || is_gimple_min_invariant (iv.step))
-                     continue;
-                   will_be_nonconstant
-                     = will_be_nonconstant_expr_predicate (parms_info, info,
-                                                           iv.step,
-                                                           nonconstant_names);
-                   if (!true_predicate_p (&will_be_nonconstant))
-                     will_be_nonconstant
-                        = and_predicates (info->conds,
-                                          &bb_predicate,
-                                          &will_be_nonconstant);
-                   if (!true_predicate_p (&will_be_nonconstant)
-                       && !false_predicate_p (&will_be_nonconstant))
-                     /* This is slightly inprecise.  We may want to represent
-                        each loop with independent predicate.  */
-                     loop_stride =
-                       and_predicates (info->conds, &loop_stride,
-                                       &will_be_nonconstant);
-                 }
-               }
+             gphi *phi = gsi.phi ();
+             tree use = gimple_phi_result (phi);
+             affine_iv iv;
+             predicate will_be_nonconstant;
+             if (virtual_operand_p (use)
+                 || !simple_iv (loop, loop, use, &iv, true)
+                 || is_gimple_min_invariant (iv.step))
+               continue;
+             will_be_nonconstant
+               = will_be_nonconstant_expr_predicate (fbi.info, info,
+                                                     iv.step,
+                                                     nonconstant_names);
+             if (!true_predicate_p (&will_be_nonconstant))
+               will_be_nonconstant = and_predicates (info->conds,
+                                                     &bb_predicate,
+                                                     &will_be_nonconstant);
+             if (!true_predicate_p (&will_be_nonconstant)
+                 && !false_predicate_p (&will_be_nonconstant))
+               /* This is slightly inprecise.  We may want to represent
+                  each loop with independent predicate.  */
+               loop_stride = and_predicates (info->conds, &loop_stride,
+                                             &will_be_nonconstant);
            }
-         free (body);
        }
       set_hint_predicate (&inline_summaries->get (node)->loop_iterations,
                          loop_iterations);
@@ -3133,6 +3124,9 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
   struct cgraph_edge *e;
   for (e = node->callees; e; e = e->next_callee)
     {
+      if (inline_edge_summary_vec.length () <= (unsigned) e->uid)
+       continue;
+
       struct inline_edge_summary *es = inline_edge_summary (e);
 
       /* Do not care about zero sized builtins.  */
@@ -3164,6 +3158,9 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
     }
   for (e = node->indirect_calls; e; e = e->next_callee)
     {
+      if (inline_edge_summary_vec.length () <= (unsigned) e->uid)
+       continue;
+
       struct inline_edge_summary *es = inline_edge_summary (e);
       if (!es->predicate
          || evaluate_predicate (es->predicate, possible_truths))
index e0fd31a..17e0a46 100644 (file)
@@ -123,6 +123,8 @@ bool
 possible_placement_new (tree type, tree expected_type,
                        HOST_WIDE_INT cur_offset)
 {
+  if (cur_offset < 0)
+    return true;
   return ((TREE_CODE (type) != RECORD_TYPE
           || !TYPE_BINFO (type)
           || cur_offset >= POINTER_SIZE
@@ -197,6 +199,8 @@ ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
           && tree_to_shwi (TYPE_SIZE (outer_type)) >= 0
           && tree_to_shwi (TYPE_SIZE (outer_type)) <= offset)
    {
+     bool der = maybe_derived_type; /* clear_outer_type will reset it.  */
+     bool dyn = dynamic;
      clear_outer_type (otr_type);
      type = otr_type;
      cur_offset = 0;
@@ -205,7 +209,7 @@ ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
        For dynamic types, we really do not have information about
        size of the memory location.  It is possible that completely
        different type is stored after outer_type.  */
-     if (!maybe_derived_type && !dynamic)
+     if (!der && !dyn)
        {
         clear_speculation ();
         invalid = true;
@@ -467,8 +471,10 @@ no_useful_type_info:
                    return true;
                }
              else
-               clear_speculation ();
-             return true;
+               {
+                 clear_speculation ();
+                 return true;
+               }
            }
          else
            {
@@ -501,15 +507,18 @@ contains_type_p (tree outer_type, HOST_WIDE_INT offset,
   if (offset < 0)
     return false;
   if (TYPE_SIZE (outer_type) && TYPE_SIZE (otr_type)
-      && TREE_CODE (outer_type) == INTEGER_CST
-      && TREE_CODE (otr_type) == INTEGER_CST
-      && wi::ltu_p (wi::to_offset (outer_type), (wi::to_offset (otr_type) + offset)))
+      && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
+      && TREE_CODE (TYPE_SIZE (otr_type)) == INTEGER_CST
+      && wi::ltu_p (wi::to_offset (TYPE_SIZE (outer_type)),
+                   (wi::to_offset (TYPE_SIZE (otr_type)) + offset)))
     return false;
 
   context.offset = offset;
   context.outer_type = TYPE_MAIN_VARIANT (outer_type);
   context.maybe_derived_type = false;
-  return context.restrict_to_inner_class (otr_type, consider_placement_new, consider_bases);
+  context.dynamic = false;
+  return context.restrict_to_inner_class (otr_type, consider_placement_new,
+                                         consider_bases);
 }
 
 
@@ -1441,7 +1450,21 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
            && TYPE_SIZE (type)
            && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
            && tree_fits_shwi_p (TYPE_SIZE (type))
-           && tree_to_shwi (TYPE_SIZE (type)) + offset > tci->offset)
+           && tree_to_shwi (TYPE_SIZE (type)) + offset > tci->offset
+           /* Some inlined constructors may look as follows:
+                 _3 = operator new (16);
+                 MEM[(struct  &)_3] ={v} {CLOBBER};
+                 MEM[(struct CompositeClass *)_3]._vptr.CompositeClass
+                   = &MEM[(void *)&_ZTV14CompositeClass + 16B];
+                 _7 = &MEM[(struct CompositeClass *)_3].object;
+                 EmptyClass::EmptyClass (_7);
+
+              When determining dynamic type of _3 and because we stop at first
+              dynamic type found, we would stop on EmptyClass::EmptyClass (_7).
+              In this case the emptyclass is not even polymorphic and we miss
+              it is contained in an outer type that is polymorphic.  */
+
+           && (tci->offset == offset || contains_polymorphic_type_p (type)))
          {
            record_known_type (tci, type, tci->offset - offset);
            return true;
@@ -1519,6 +1542,7 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
   /* Remember OFFSET before it is modified by restrict_to_inner_class.
      This is because we do not update INSTANCE when walking inwards.  */
   HOST_WIDE_INT instance_offset = offset;
+  tree instance_outer_type = outer_type;
 
   if (otr_type)
     otr_type = TYPE_MAIN_VARIANT (otr_type);
@@ -1599,7 +1623,7 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
        }
     }
  
-  /* If we failed to look up the refernece in code, build our own.  */
+  /* If we failed to look up the reference in code, build our own.  */
   if (!instance_ref)
     {
       /* If the statement in question does not use memory, we can't tell
@@ -1629,13 +1653,13 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
       print_generic_expr (dump_file, otr_object, TDF_SLIM);
       fprintf (dump_file, "  Outer instance pointer: ");
       print_generic_expr (dump_file, instance, TDF_SLIM);
-      fprintf (dump_file, " offset: %i (bits)", (int)offset);
+      fprintf (dump_file, " offset: %i (bits)", (int)instance_offset);
       fprintf (dump_file, " vtbl reference: ");
       print_generic_expr (dump_file, instance_ref, TDF_SLIM);
       fprintf (dump_file, "\n");
     }
 
-  tci.offset = offset;
+  tci.offset = instance_offset;
   tci.instance = instance;
   tci.vtbl_ptr_ref = instance_ref;
   gcc_assert (TREE_CODE (instance) != MEM_REF);
@@ -1701,9 +1725,12 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
          && !dynamic
          && !tci.seen_unanalyzed_store
          && !tci.multiple_types_encountered
-         && offset == tci.offset
-         && types_same_for_odr (tci.known_current_type,
-                                outer_type)))
+         && ((offset == tci.offset
+              && types_same_for_odr (tci.known_current_type,
+                                     outer_type))
+              || (instance_offset == offset
+                  && types_same_for_odr (tci.known_current_type,
+                                         instance_outer_type)))))
     {
       if (!outer_type || tci.seen_unanalyzed_store)
        return false;
index d828ccf..9298fac 100644 (file)
@@ -99,57 +99,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "domwalk.h"
 #include "builtins.h"
 
-/* Intermediate information that we get from alias analysis about a particular
-   parameter in a particular basic_block.  When a parameter or the memory it
-   references is marked modified, we use that information in all dominatd
-   blocks without cosulting alias analysis oracle.  */
-
-struct param_aa_status
-{
-  /* Set when this structure contains meaningful information.  If not, the
-     structure describing a dominating BB should be used instead.  */
-  bool valid;
-
-  /* Whether we have seen something which might have modified the data in
-     question.  PARM is for the parameter itself, REF is for data it points to
-     but using the alias type of individual accesses and PT is the same thing
-     but for computing aggregate pass-through functions using a very inclusive
-     ao_ref.  */
-  bool parm_modified, ref_modified, pt_modified;
-};
-
-/* Information related to a given BB that used only when looking at function
-   body.  */
-
-struct ipa_bb_info
-{
-  /* Call graph edges going out of this BB.  */
-  vec<cgraph_edge *> cg_edges;
-  /* Alias analysis statuses of each formal parameter at this bb.  */
-  vec<param_aa_status> param_aa_statuses;
-};
-
-/* Structure with global information that is only used when looking at function
-   body. */
-
-struct func_body_info
-{
-  /* The node that is being analyzed.  */
-  cgraph_node *node;
-
-  /* Its info.  */
-  struct ipa_node_params *info;
-
-  /* Information about individual BBs. */
-  vec<ipa_bb_info> bb_infos;
-
-  /* Number of parameters.  */
-  int param_count;
-
-  /* Number of statements already walked by when analyzing this function.  */
-  unsigned int aa_walked;
-};
-
 /* Function summary where the parameter infos are actually stored. */
 ipa_node_params_t *ipa_node_params_sum = NULL;
 /* Vector of IPA-CP transformation data for each clone.  */
@@ -563,7 +512,7 @@ ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
    of this function body.  */
 
 static struct ipa_bb_info *
-ipa_get_bb_info (struct func_body_info *fbi, basic_block bb)
+ipa_get_bb_info (struct ipa_func_body_info *fbi, basic_block bb)
 {
   gcc_checking_assert (fbi);
   return &fbi->bb_infos[bb->index];
@@ -838,7 +787,7 @@ mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
    should really just start giving up.  */
 
 static bool
-aa_overwalked (struct func_body_info *fbi)
+aa_overwalked (struct ipa_func_body_info *fbi)
 {
   gcc_checking_assert (fbi);
   return fbi->aa_walked > (unsigned) PARAM_VALUE (PARAM_IPA_MAX_AA_STEPS);
@@ -847,8 +796,8 @@ aa_overwalked (struct func_body_info *fbi)
 /* Find the nearest valid aa status for parameter specified by INDEX that
    dominates BB.  */
 
-static struct param_aa_status *
-find_dominating_aa_status (struct func_body_info *fbi, basic_block bb,
+static struct ipa_param_aa_status *
+find_dominating_aa_status (struct ipa_func_body_info *fbi, basic_block bb,
                           int index)
 {
   while (true)
@@ -867,21 +816,21 @@ find_dominating_aa_status (struct func_body_info *fbi, basic_block bb,
    structures and/or intialize the result with a dominating description as
    necessary.  */
 
-static struct param_aa_status *
-parm_bb_aa_status_for_bb (struct func_body_info *fbi, basic_block bb,
+static struct ipa_param_aa_status *
+parm_bb_aa_status_for_bb (struct ipa_func_body_info *fbi, basic_block bb,
                          int index)
 {
   gcc_checking_assert (fbi);
   struct ipa_bb_info *bi = ipa_get_bb_info (fbi, bb);
   if (bi->param_aa_statuses.is_empty ())
     bi->param_aa_statuses.safe_grow_cleared (fbi->param_count);
-  struct param_aa_status *paa = &bi->param_aa_statuses[index];
+  struct ipa_param_aa_status *paa = &bi->param_aa_statuses[index];
   if (!paa->valid)
     {
       gcc_checking_assert (!paa->parm_modified
                           && !paa->ref_modified
                           && !paa->pt_modified);
-      struct param_aa_status *dom_paa;
+      struct ipa_param_aa_status *dom_paa;
       dom_paa = find_dominating_aa_status (fbi, bb, index);
       if (dom_paa)
        *paa = *dom_paa;
@@ -898,10 +847,10 @@ parm_bb_aa_status_for_bb (struct func_body_info *fbi, basic_block bb,
    gathered but do not survive the summary building stage.  */
 
 static bool
-parm_preserved_before_stmt_p (struct func_body_info *fbi, int index,
+parm_preserved_before_stmt_p (struct ipa_func_body_info *fbi, int index,
                              gimple stmt, tree parm_load)
 {
-  struct param_aa_status *paa;
+  struct ipa_param_aa_status *paa;
   bool modified = false;
   ao_ref refd;
 
@@ -937,7 +886,7 @@ parm_preserved_before_stmt_p (struct func_body_info *fbi, int index,
    modified.  Otherwise return -1.  */
 
 static int
-load_from_unmodified_param (struct func_body_info *fbi,
+load_from_unmodified_param (struct ipa_func_body_info *fbi,
                            vec<ipa_param_descriptor> descriptors,
                            gimple stmt)
 {
@@ -964,10 +913,10 @@ load_from_unmodified_param (struct func_body_info *fbi,
    before reaching statement STMT.  */
 
 static bool
-parm_ref_data_preserved_p (struct func_body_info *fbi,
+parm_ref_data_preserved_p (struct ipa_func_body_info *fbi,
                           int index, gimple stmt, tree ref)
 {
-  struct param_aa_status *paa;
+  struct ipa_param_aa_status *paa;
   bool modified = false;
   ao_ref refd;
 
@@ -1003,7 +952,7 @@ parm_ref_data_preserved_p (struct func_body_info *fbi,
    CALL into which it is passed.  FBI describes the function body.  */
 
 static bool
-parm_ref_data_pass_through_p (struct func_body_info *fbi, int index,
+parm_ref_data_pass_through_p (struct ipa_func_body_info *fbi, int index,
                              gimple call, tree parm)
 {
   bool modified = false;
@@ -1017,8 +966,9 @@ parm_ref_data_pass_through_p (struct func_body_info *fbi, int index,
       || aa_overwalked (fbi))
     return false;
 
-  struct param_aa_status *paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (call),
-                                                         index);
+  struct ipa_param_aa_status *paa = parm_bb_aa_status_for_bb (fbi,
+                                                             gimple_bb (call),
+                                                             index);
   if (paa->pt_modified)
     return false;
 
@@ -1041,12 +991,12 @@ parm_ref_data_pass_through_p (struct func_body_info *fbi, int index,
    within the aggregate and whether it is a load from a value passed by
    reference respectively.  */
 
-static bool
-ipa_load_from_parm_agg_1 (struct func_body_info *fbi,
-                         vec<ipa_param_descriptor> descriptors,
-                         gimple stmt, tree op, int *index_p,
-                         HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p,
-                         bool *by_ref_p)
+bool
+ipa_load_from_parm_agg (struct ipa_func_body_info *fbi,
+                       vec<ipa_param_descriptor> descriptors,
+                       gimple stmt, tree op, int *index_p,
+                       HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p,
+                       bool *by_ref_p)
 {
   int index;
   HOST_WIDE_INT size, max_size;
@@ -1113,18 +1063,6 @@ ipa_load_from_parm_agg_1 (struct func_body_info *fbi,
   return false;
 }
 
-/* Just like the previous function, just without the param_analysis_info
-   pointer, for users outside of this file.  */
-
-bool
-ipa_load_from_parm_agg (struct ipa_node_params *info, gimple stmt,
-                       tree op, int *index_p, HOST_WIDE_INT *offset_p,
-                       bool *by_ref_p)
-{
-  return ipa_load_from_parm_agg_1 (NULL, info->descriptors, stmt, op, index_p,
-                                  offset_p, NULL, by_ref_p);
-}
-
 /* Given that an actual argument is an SSA_NAME (given in NAME) and is a result
    of an assignment statement STMT, try to determine whether we are actually
    handling any of the following cases and construct an appropriate jump
@@ -1179,7 +1117,7 @@ ipa_load_from_parm_agg (struct ipa_node_params *info, gimple stmt,
    only needed for intraprocedural analysis.  */
 
 static void
-compute_complex_assign_jump_func (struct func_body_info *fbi,
+compute_complex_assign_jump_func (struct ipa_func_body_info *fbi,
                                  struct ipa_node_params *info,
                                  struct ipa_jump_func *jfunc,
                                  gcall *call, gimple stmt, tree name,
@@ -1321,7 +1259,7 @@ get_ancestor_addr_info (gimple assign, tree *obj_p, HOST_WIDE_INT *offset)
      return D.1879_6;  */
 
 static void
-compute_complex_ancestor_jump_func (struct func_body_info *fbi,
+compute_complex_ancestor_jump_func (struct ipa_func_body_info *fbi,
                                    struct ipa_node_params *info,
                                    struct ipa_jump_func *jfunc,
                                    gcall *call, gphi *phi)
@@ -1703,7 +1641,7 @@ ipa_get_callee_param_type (struct cgraph_edge *e, int i)
    to this callsite.  */
 
 static void
-ipa_compute_jump_functions_for_edge (struct func_body_info *fbi,
+ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
                                     struct cgraph_edge *cs)
 {
   struct ipa_node_params *info = IPA_NODE_REF (cs->caller);
@@ -1826,7 +1764,7 @@ ipa_compute_jump_functions_for_edge (struct func_body_info *fbi,
    from BB.  */
 
 static void
-ipa_compute_jump_functions_for_bb (struct func_body_info *fbi, basic_block bb)
+ipa_compute_jump_functions_for_bb (struct ipa_func_body_info *fbi, basic_block bb)
 {
   struct ipa_bb_info *bi = ipa_get_bb_info (fbi, bb);
   int i;
@@ -1989,7 +1927,7 @@ ipa_note_param_call (struct cgraph_node *node, int param_index,
    passed by value or reference.  */
 
 static void
-ipa_analyze_indirect_call_uses (struct func_body_info *fbi, gcall *call,
+ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call,
                                tree target)
 {
   struct ipa_node_params *info = fbi->info;
@@ -2008,9 +1946,9 @@ ipa_analyze_indirect_call_uses (struct func_body_info *fbi, gcall *call,
   int index;
   gimple def = SSA_NAME_DEF_STMT (target);
   if (gimple_assign_single_p (def)
-      && ipa_load_from_parm_agg_1 (fbi, info->descriptors, def,
-                                  gimple_assign_rhs1 (def), &index, &offset,
-                                  NULL, &by_ref))
+      && ipa_load_from_parm_agg (fbi, info->descriptors, def,
+                                gimple_assign_rhs1 (def), &index, &offset,
+                                NULL, &by_ref))
     {
       struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
       cs->indirect_info->offset = offset;
@@ -2127,7 +2065,7 @@ ipa_analyze_indirect_call_uses (struct func_body_info *fbi, gcall *call,
    statement.  */
 
 static void
-ipa_analyze_virtual_call_uses (struct func_body_info *fbi,
+ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi,
                               gcall *call, tree target)
 {
   tree obj = OBJ_TYPE_REF_OBJECT (target);
@@ -2184,7 +2122,7 @@ ipa_analyze_virtual_call_uses (struct func_body_info *fbi,
    containing intermediate information about each formal parameter.  */
 
 static void
-ipa_analyze_call_uses (struct func_body_info *fbi, gcall *call)
+ipa_analyze_call_uses (struct ipa_func_body_info *fbi, gcall *call)
 {
   tree target = gimple_call_fn (call);
 
@@ -2230,7 +2168,7 @@ ipa_analyze_call_uses (struct func_body_info *fbi, gcall *call)
    formal parameters are called.  */
 
 static void
-ipa_analyze_stmt_uses (struct func_body_info *fbi, gimple stmt)
+ipa_analyze_stmt_uses (struct ipa_func_body_info *fbi, gimple stmt)
 {
   if (is_gimple_call (stmt))
     ipa_analyze_call_uses (fbi, as_a <gcall *> (stmt));
@@ -2263,7 +2201,7 @@ visit_ref_for_mod_analysis (gimple, tree op, tree, void *data)
    the function being analyzed.  */
 
 static void
-ipa_analyze_params_uses_in_bb (struct func_body_info *fbi, basic_block bb)
+ipa_analyze_params_uses_in_bb (struct ipa_func_body_info *fbi, basic_block bb)
 {
   gimple_stmt_iterator gsi;
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -2345,13 +2283,13 @@ free_ipa_bb_info (struct ipa_bb_info *bi)
 class analysis_dom_walker : public dom_walker
 {
 public:
-  analysis_dom_walker (struct func_body_info *fbi)
+  analysis_dom_walker (struct ipa_func_body_info *fbi)
     : dom_walker (CDI_DOMINATORS), m_fbi (fbi) {}
 
   virtual void before_dom_children (basic_block);
 
 private:
-  struct func_body_info *m_fbi;
+  struct ipa_func_body_info *m_fbi;
 };
 
 void
@@ -2368,7 +2306,7 @@ analysis_dom_walker::before_dom_children (basic_block bb)
 void
 ipa_analyze_node (struct cgraph_node *node)
 {
-  struct func_body_info fbi;
+  struct ipa_func_body_info fbi;
   struct ipa_node_params *info;
 
   ipa_check_create_node_params ();
@@ -5187,7 +5125,7 @@ adjust_agg_replacement_values (struct cgraph_node *node,
 class ipcp_modif_dom_walker : public dom_walker
 {
 public:
-  ipcp_modif_dom_walker (struct func_body_info *fbi,
+  ipcp_modif_dom_walker (struct ipa_func_body_info *fbi,
                         vec<ipa_param_descriptor> descs,
                         struct ipa_agg_replacement_value *av,
                         bool *sc, bool *cc)
@@ -5197,7 +5135,7 @@ public:
   virtual void before_dom_children (basic_block);
 
 private:
-  struct func_body_info *m_fbi;
+  struct ipa_func_body_info *m_fbi;
   vec<ipa_param_descriptor> m_descriptors;
   struct ipa_agg_replacement_value *m_aggval;
   bool *m_something_changed, *m_cfg_changed;
@@ -5238,8 +5176,8 @@ ipcp_modif_dom_walker::before_dom_children (basic_block bb)
       if (vce)
        continue;
 
-      if (!ipa_load_from_parm_agg_1 (m_fbi, m_descriptors, stmt, rhs, &index,
-                                    &offset, &size, &by_ref))
+      if (!ipa_load_from_parm_agg (m_fbi, m_descriptors, stmt, rhs, &index,
+                                  &offset, &size, &by_ref))
        continue;
       for (v = m_aggval; v; v = v->next)
        if (v->index == index
@@ -5355,7 +5293,7 @@ unsigned int
 ipcp_transform_function (struct cgraph_node *node)
 {
   vec<ipa_param_descriptor> descriptors = vNULL;
-  struct func_body_info fbi;
+  struct ipa_func_body_info fbi;
   struct ipa_agg_replacement_value *aggval;
   int param_count;
   bool cfg_changed = false, something_changed = false;
index 0488254..7d5336d 100644 (file)
@@ -336,6 +336,57 @@ struct ipa_node_params
   unsigned node_calling_single_call : 1;
 };
 
+/* Intermediate information that we get from alias analysis about a particular
+   parameter in a particular basic_block.  When a parameter or the memory it
+   references is marked modified, we use that information in all dominated
+   blocks without consulting alias analysis oracle.  */
+
+struct ipa_param_aa_status
+{
+  /* Set when this structure contains meaningful information.  If not, the
+     structure describing a dominating BB should be used instead.  */
+  bool valid;
+
+  /* Whether we have seen something which might have modified the data in
+     question.  PARM is for the parameter itself, REF is for data it points to
+     but using the alias type of individual accesses and PT is the same thing
+     but for computing aggregate pass-through functions using a very inclusive
+     ao_ref.  */
+  bool parm_modified, ref_modified, pt_modified;
+};
+
+/* Information related to a given BB that used only when looking at function
+   body.  */
+
+struct ipa_bb_info
+{
+  /* Call graph edges going out of this BB.  */
+  vec<cgraph_edge *> cg_edges;
+  /* Alias analysis statuses of each formal parameter at this bb.  */
+  vec<ipa_param_aa_status> param_aa_statuses;
+};
+
+/* Structure with global information that is only used when looking at function
+   body. */
+
+struct ipa_func_body_info
+{
+  /* The node that is being analyzed.  */
+  cgraph_node *node;
+
+  /* Its info.  */
+  struct ipa_node_params *info;
+
+  /* Information about individual BBs. */
+  vec<ipa_bb_info> bb_infos;
+
+  /* Number of parameters.  */
+  int param_count;
+
+  /* Number of statements already walked by when analyzing this function.  */
+  unsigned int aa_walked;
+};
+
 /* ipa_node_params access functions.  Please use these to access fields that
    are or will be shared among various passes.  */
 
@@ -585,8 +636,9 @@ void ipa_analyze_node (struct cgraph_node *);
 /* Aggregate jump function related functions.  */
 tree ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *, HOST_WIDE_INT,
                                 bool);
-bool ipa_load_from_parm_agg (struct ipa_node_params *, gimple, tree, int *,
-                            HOST_WIDE_INT *, bool *);
+bool ipa_load_from_parm_agg (struct ipa_func_body_info *,
+                            vec<ipa_param_descriptor>, gimple, tree, int *,
+                            HOST_WIDE_INT *, HOST_WIDE_INT *, bool *);
 
 /* Debugging interface.  */
 void ipa_print_node_params (FILE *, struct cgraph_node *node);
index ff1fe8a..e104f00 100644 (file)
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "reload.h"
 #include "params.h"
 #include "df.h"
+#include "recog.h"
 #include "ira-int.h"
 
 typedef struct allocno_hard_regs *allocno_hard_regs_t;
index c2853dc..c1c545c 100644 (file)
@@ -1045,6 +1045,8 @@ extern void ira_debug_live_ranges (void);
 extern void ira_create_allocno_live_ranges (void);
 extern void ira_compress_allocno_live_ranges (void);
 extern void ira_finish_allocno_live_ranges (void);
+extern void ira_implicitly_set_insn_hard_regs (HARD_REG_SET *,
+                                              alternative_mask);
 
 /* ira-conflicts.c */
 extern void ira_debug_conflicts (bool);
index b29f572..81d3208 100644 (file)
@@ -837,7 +837,8 @@ single_reg_operand_class (int op_num)
    might be used by insn reloads because the constraints are too
    strict.  */
 void
-ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set)
+ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set,
+                                  alternative_mask preferred)
 {
   int i, c, regno = 0;
   enum reg_class cl;
@@ -860,7 +861,6 @@ ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set)
          mode = (GET_CODE (op) == SCRATCH
                  ? GET_MODE (op) : PSEUDO_REGNO_MODE (regno));
          cl = NO_REGS;
-         alternative_mask preferred = preferred_alternatives;
          for (; (c = *p); p += CONSTRAINT_LEN (c, p))
            if (c == '#')
              preferred &= ~ALTERNATIVE_BIT (0);
index ea2b69f..e63b0fa 100644 (file)
@@ -2296,9 +2296,12 @@ ira_setup_eliminable_regset (void)
   frame_pointer_needed
     = (! flag_omit_frame_pointer
        || (cfun->calls_alloca && EXIT_IGNORE_STACK)
-       /* We need the frame pointer to catch stack overflow exceptions
-         if the stack pointer is moving.  */
-       || (flag_stack_check && STACK_CHECK_MOVING_SP)
+       /* We need the frame pointer to catch stack overflow exceptions if
+         the stack pointer is moving (as for the alloca case just above).  */
+       || (STACK_CHECK_MOVING_SP
+          && flag_stack_check
+          && flag_exceptions
+          && cfun->can_throw_non_call_exceptions)
        || crtl->accesses_prior_frames
        || (SUPPORTS_STACK_ALIGNMENT && crtl->stack_realign_needed)
        /* We need a frame pointer for all Cilk Plus functions that use
index 1979780..dca99e8 100644 (file)
@@ -190,7 +190,6 @@ extern void ira_init (void);
 extern void ira_setup_eliminable_regset (void);
 extern rtx ira_eliminate_regs (rtx, machine_mode);
 extern void ira_set_pseudo_classes (bool, FILE *);
-extern void ira_implicitly_set_insn_hard_regs (HARD_REG_SET *);
 extern void ira_expand_reg_equiv (void);
 extern void ira_update_equiv_info_by_shuffle_insn (int, int, rtx_insn *);
 
index 4f2480e..c79a515 100644 (file)
@@ -1340,7 +1340,7 @@ process_addr_reg (rtx *loc, bool check_only_p, rtx_insn **before, rtx_insn **aft
   if (after != NULL)
     {
       start_sequence ();
-      lra_emit_move (reg, new_reg);
+      lra_emit_move (before_p ? copy_rtx (reg) : reg, new_reg);
       emit_insn (*after);
       *after = get_insns ();
       end_sequence ();
@@ -3738,7 +3738,8 @@ curr_insn_transform (bool check_only_p)
                 assigment pass and the scratch pseudo will be
                 spilled.  Spilled scratch pseudos are transformed
                 back to scratches at the LRA end.  */
-             && lra_former_scratch_operand_p (curr_insn, i))
+             && lra_former_scratch_operand_p (curr_insn, i)
+             && lra_former_scratch_p (REGNO (op)))
            {
              int regno = REGNO (op);
              lra_change_class (regno, NO_REGS, "      Change to", true);
@@ -3747,6 +3748,8 @@ curr_insn_transform (bool check_only_p)
                   spilled pseudo as there is only one such insn, the
                   current one.  */
                reg_renumber[regno] = -1;
+             lra_assert (bitmap_single_bit_set_p
+                         (&lra_reg_info[REGNO (op)].insn_bitmap));
            }
          /* We can do an optional reload.  If the pseudo got a hard
             reg, we might improve the code through inheritance.  If
@@ -4729,7 +4732,7 @@ inherit_reload_reg (bool def_p, int original_regno,
        }
       return false;
     }
-  lra_substitute_pseudo_within_insn (insn, original_regno, new_reg);
+  lra_substitute_pseudo_within_insn (insn, original_regno, new_reg, false);
   lra_update_insn_regno_info (insn);
   if (! def_p)
     /* We now have a new usage insn for original regno.  */
@@ -4761,7 +4764,7 @@ inherit_reload_reg (bool def_p, int original_regno,
          lra_assert (DEBUG_INSN_P (usage_insn));
          next_usage_insns = XEXP (next_usage_insns, 1);
        }
-      lra_substitute_pseudo (&usage_insn, original_regno, new_reg);
+      lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false);
       lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn));
       if (lra_dump_file != NULL)
        {
@@ -5023,7 +5026,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
       usage_insn = XEXP (next_usage_insns, 0);
       lra_assert (DEBUG_INSN_P (usage_insn));
       next_usage_insns = XEXP (next_usage_insns, 1);
-      lra_substitute_pseudo (&usage_insn, original_regno, new_reg);
+      lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false);
       lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn));
       if (lra_dump_file != NULL)
        {
@@ -5955,8 +5958,9 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
                    {
                      if (change_p && bitmap_bit_p (remove_pseudos, regno))
                        {
-                         lra_substitute_pseudo_within_insn (
-                           curr_insn, regno, regno_reg_rtx[restore_regno]);
+                         lra_substitute_pseudo_within_insn
+                           (curr_insn, regno, regno_reg_rtx[restore_regno],
+                            false);
                          restored_regs_p = true;
                        }
                      else
@@ -6079,9 +6083,9 @@ undo_optional_reloads (void)
                 we remove the inheritance pseudo and the optional
                 reload.  */
            }
-         lra_substitute_pseudo_within_insn (
-           insn, regno,
-           regno_reg_rtx[lra_reg_info[regno].restore_regno]);
+         lra_substitute_pseudo_within_insn
+           (insn, regno, regno_reg_rtx[lra_reg_info[regno].restore_regno],
+            false);
          lra_update_insn_regno_info (insn);
          if (lra_dump_file != NULL)
            {
index 259c4c7..32ada4b 100644 (file)
@@ -314,8 +314,8 @@ extern void lra_update_dups (lra_insn_recog_data_t, signed char *);
 extern void lra_process_new_insns (rtx_insn *, rtx_insn *, rtx_insn *,
                                   const char *);
 
-extern bool lra_substitute_pseudo (rtx *, int, rtx);
-extern bool lra_substitute_pseudo_within_insn (rtx_insn *, int, rtx);
+extern bool lra_substitute_pseudo (rtx *, int, rtx, bool);
+extern bool lra_substitute_pseudo_within_insn (rtx_insn *, int, rtx, bool);
 
 extern lra_insn_recog_data_t lra_set_insn_recog_data (rtx_insn *);
 extern lra_insn_recog_data_t lra_update_insn_recog_data (rtx_insn *);
index eee5f19..fd9e29c 100644 (file)
@@ -759,7 +759,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
                    {
                      insn = lra_insn_recog_data[uid]->insn;
                      lra_substitute_pseudo_within_insn (insn, dst_regno,
-                                                        SET_SRC (set));
+                                                        SET_SRC (set), true);
                      lra_update_insn_regno_info (insn);
                    }
                }
index a23cb5b..f2d226c 100644 (file)
@@ -432,6 +432,16 @@ operand_to_remat (rtx_insn *insn)
          return -1;
        found_reg = reg;
       }
+    /* IRA calculates conflicts separately for subregs of two words
+       pseudo.  Even if the pseudo lives, e.g. one its subreg can be
+       used lately, another subreg hard register can be already used
+       for something else.  In such case, it is not safe to
+       rematerialize the insn.  */
+    else if (reg->type == OP_IN && reg->subreg_p
+            && reg->regno >= FIRST_PSEUDO_REGISTER
+            && (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno))
+                == 2 * UNITS_PER_WORD))
+      return -1;
   if (found_reg == NULL)
     return -1;
   if (found_reg->regno < FIRST_PSEUDO_REGISTER)
@@ -722,12 +732,17 @@ calculate_local_reg_remat_bb_data (void)
 static bool
 input_regno_present_p (rtx_insn *insn, int regno)
 {
+  int iter;
   lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
+  struct lra_static_insn_data *static_id = id->insn_static_data;
   struct lra_insn_reg *reg;
-
-  for (reg = id->regs; reg != NULL; reg = reg->next)
-    if (reg->type == OP_IN && reg->regno == regno)
-      return true;
+  
+  for (iter = 0; iter < 2; iter++)
+    for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
+        reg != NULL;
+        reg = reg->next)
+      if (reg->type == OP_IN && reg->regno == regno)
+       return true;
   return false;
 }
 
@@ -735,13 +750,18 @@ input_regno_present_p (rtx_insn *insn, int regno)
 static bool
 call_used_input_regno_present_p (rtx_insn *insn)
 {
+  int iter;
   lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
+  struct lra_static_insn_data *static_id = id->insn_static_data;
   struct lra_insn_reg *reg;
 
-  for (reg = id->regs; reg != NULL; reg = reg->next)
-    if (reg->type == OP_IN && reg->regno <= FIRST_PSEUDO_REGISTER
-       && TEST_HARD_REG_BIT (call_used_reg_set, reg->regno))
-      return true;
+  for (iter = 0; iter < 2; iter++)
+    for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
+        reg != NULL;
+        reg = reg->next)
+      if (reg->type == OP_IN && reg->regno <= FIRST_PSEUDO_REGISTER
+         && TEST_HARD_REG_BIT (call_used_reg_set, reg->regno))
+       return true;
   return false;
 }
 
@@ -788,11 +808,13 @@ calculate_gen_cands (void)
        if (INSN_P (insn))
          {
            lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
+           struct lra_static_insn_data *static_id = id->insn_static_data;
            struct lra_insn_reg *reg;
            unsigned int uid;
            bitmap_iterator bi;
            cand_t cand;
            rtx set;
+           int iter;
            int src_regno = -1, dst_regno = -1;
 
            if ((set = single_set (insn)) != NULL
@@ -804,26 +826,29 @@ calculate_gen_cands (void)
 
            /* Update gen_cands:  */
            bitmap_clear (&temp_bitmap);
-           for (reg = id->regs; reg != NULL; reg = reg->next)
-             if (reg->type != OP_IN
-                 || find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
-               EXECUTE_IF_SET_IN_BITMAP (&gen_insns, 0, uid, bi)
-                 {
-                   rtx_insn *insn2 = lra_insn_recog_data[uid]->insn;
-
-                   cand = insn_to_cand[INSN_UID (insn2)];
-                   gcc_assert (cand != NULL);
-                   /* Ignore the reload insn.  */
-                   if (src_regno == cand->reload_regno
-                       && dst_regno == cand->regno)
-                     continue;
-                   if (cand->regno == reg->regno
-                       || input_regno_present_p (insn2, reg->regno))
-                     {
-                       bitmap_clear_bit (gen_cands, cand->index);
-                       bitmap_set_bit (&temp_bitmap, uid);
-                     }
-                 }
+           for (iter = 0; iter < 2; iter++)
+             for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
+                  reg != NULL;
+                  reg = reg->next)
+               if (reg->type != OP_IN
+                   || find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
+                 EXECUTE_IF_SET_IN_BITMAP (&gen_insns, 0, uid, bi)
+                   {
+                     rtx_insn *insn2 = lra_insn_recog_data[uid]->insn;
+                     
+                     cand = insn_to_cand[INSN_UID (insn2)];
+                     gcc_assert (cand != NULL);
+                     /* Ignore the reload insn.  */
+                     if (src_regno == cand->reload_regno
+                         && dst_regno == cand->regno)
+                       continue;
+                     if (cand->regno == reg->regno
+                         || input_regno_present_p (insn2, reg->regno))
+                       {
+                         bitmap_clear_bit (gen_cands, cand->index);
+                         bitmap_set_bit (&temp_bitmap, uid);
+                       }
+                   }
            
            if (CALL_P (insn))
              EXECUTE_IF_SET_IN_BITMAP (&gen_insns, 0, uid, bi)
@@ -1097,6 +1122,7 @@ do_remat (void)
          unsigned int cid;
          bitmap_iterator bi;
          rtx set;
+         int iter;
          int src_regno = -1, dst_regno = -1;
 
          if ((set = single_set (insn)) != NULL
@@ -1182,21 +1208,24 @@ do_remat (void)
          bitmap_clear (&temp_bitmap);
          /* Update avail_cands (see analogous code for
             calculate_gen_cands).  */
-         for (reg = id->regs; reg != NULL; reg = reg->next)
-           if (reg->type != OP_IN
-               || find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
-             EXECUTE_IF_SET_IN_BITMAP (&avail_cands, 0, cid, bi)
-               {
-                 cand = all_cands[cid];
-
-                 /* Ignore the reload insn.  */
-                 if (src_regno == cand->reload_regno
-                     && dst_regno == cand->regno)
-                   continue;
-                 if (cand->regno == reg->regno
-                     || input_regno_present_p (cand->insn, reg->regno))
-                   bitmap_set_bit (&temp_bitmap, cand->index);
-               }
+         for (iter = 0; iter < 2; iter++)
+           for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
+                reg != NULL;
+                reg = reg->next)
+             if (reg->type != OP_IN
+                 || find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
+               EXECUTE_IF_SET_IN_BITMAP (&avail_cands, 0, cid, bi)
+                 {
+                   cand = all_cands[cid];
+                   
+                   /* Ignore the reload insn.  */
+                   if (src_regno == cand->reload_regno
+                       && dst_regno == cand->regno)
+                     continue;
+                   if (cand->regno == reg->regno
+                       || input_regno_present_p (cand->insn, reg->regno))
+ &nbs