]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Merge in trunk.
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 4 Nov 2013 21:29:11 +0000 (21:29 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 4 Nov 2013 21:29:11 +0000 (21:29 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@204366 138bc75d-0d04-0410-961f-82ee72b054a4

144 files changed:
1  2 
gcc/Makefile.in
gcc/ada/gcc-interface/decl.c
gcc/ada/gcc-interface/trans.c
gcc/ada/gcc-interface/utils.c
gcc/alias.c
gcc/asan.c
gcc/builtins.c
gcc/c-family/c-ada-spec.c
gcc/c-family/c-common.c
gcc/c-family/c-cppbuiltin.c
gcc/c-family/c-format.c
gcc/c-family/c-lex.c
gcc/c-family/c-pragma.c
gcc/c-family/cilk.c
gcc/c/c-decl.c
gcc/c/c-parser.c
gcc/c/c-typeck.c
gcc/cfgexpand.c
gcc/cfgloop.c
gcc/cgraph.c
gcc/cgraphunit.c
gcc/cilk-common.c
gcc/config/aarch64/aarch64.c
gcc/config/arm/arm.c
gcc/config/avr/avr.c
gcc/config/darwin.c
gcc/config/i386/i386.c
gcc/config/mips/mips.c
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/sh/sh.c
gcc/coverage.c
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck2.c
gcc/cppbuiltin.c
gcc/dbxout.c
gcc/doc/generic.texi
gcc/doc/rtl.texi
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/dwarf2out.c
gcc/except.c
gcc/expmed.c
gcc/expr.c
gcc/expr.h
gcc/final.c
gcc/fold-const.c
gcc/fortran/target-memory.c
gcc/fortran/trans-types.c
gcc/function.c
gcc/gcse.c
gcc/genemit.c
gcc/gengtype-parse.c
gcc/gengtype-state.c
gcc/gengtype.c
gcc/genmodes.c
gcc/gimple-fold.c
gcc/gimple-pretty-print.c
gcc/gimple-ssa-strength-reduction.c
gcc/gimple.c
gcc/gimplify.c
gcc/go/gofrontend/expressions.cc
gcc/graphite-clast-to-gimple.c
gcc/graphite-scop-detection.c
gcc/graphite-sese-to-poly.c
gcc/ipa-cp.c
gcc/ipa-devirt.c
gcc/ipa-prop.c
gcc/ipa-utils.h
gcc/loop-unroll.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/lto/lto-lang.c
gcc/lto/lto.c
gcc/machmode.def
gcc/omp-low.c
gcc/optabs.c
gcc/predict.c
gcc/print-tree.c
gcc/recog.c
gcc/stor-layout.c
gcc/targhooks.c
gcc/trans-mem.c
gcc/tree-call-cdce.c
gcc/tree-cfg.c
gcc/tree-chrec.c
gcc/tree-core.h
gcc/tree-data-ref.c
gcc/tree-dfa.c
gcc/tree-inline.c
gcc/tree-object-size.c
gcc/tree-predcom.c
gcc/tree-pretty-print.c
gcc/tree-sra.c
gcc/tree-ssa-address.c
gcc/tree-ssa-alias.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-forwprop.c
gcc/tree-ssa-loop-im.c
gcc/tree-ssa-loop-ivcanon.c
gcc/tree-ssa-loop-ivopts.c
gcc/tree-ssa-loop-niter.c
gcc/tree-ssa-loop-prefetch.c
gcc/tree-ssa-loop.h
gcc/tree-ssa-math-opts.c
gcc/tree-ssa-phiopt.c
gcc/tree-ssa-pre.c
gcc/tree-ssa-reassoc.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-strlen.c
gcc/tree-ssa-structalias.c
gcc/tree-ssa-uninit.c
gcc/tree-ssa.c
gcc/tree-ssanames.c
gcc/tree-ssanames.h
gcc/tree-stdarg.c
gcc/tree-streamer-in.c
gcc/tree-streamer-out.c
gcc/tree-switch-conversion.c
gcc/tree-vect-data-refs.c
gcc/tree-vect-generic.c
gcc/tree-vect-loop-manip.c
gcc/tree-vect-loop.c
gcc/tree-vect-patterns.c
gcc/tree-vect-stmts.c
gcc/tree-vectorizer.h
gcc/tree-vrp.c
gcc/tree.c
gcc/tree.def
gcc/tree.h
gcc/tsan.c
gcc/value-prof.c
gcc/var-tracking.c
gcc/varasm.c

diff --cc gcc/Makefile.in
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/alias.c
Simple merge
diff --cc gcc/asan.c
Simple merge
diff --cc gcc/builtins.c
Simple merge
index 89379dbe4c8d01a68dafa59c30a996a60dcd1660,3f325e77098776fb4734deaabacc6460726e0da0..bdba8f98ea141a01cc5bbadcdde35ceb064572fa
@@@ -29,23 -29,32 +29,18 @@@ along with GCC; see the file COPYING3
  #include "cpplib.h"
  #include "c-pragma.h"
  #include "cpp-id-data.h"
 -
 -/* Adapted from hwint.h to use the Ada prefix.  */
 -#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
 -# if HOST_BITS_PER_WIDE_INT == 64
 -#  define ADA_HOST_WIDE_INT_PRINT_DOUBLE_HEX \
 -     "16#%" HOST_LONG_FORMAT "x%016" HOST_LONG_FORMAT "x#"
 -# else
 -#  define ADA_HOST_WIDE_INT_PRINT_DOUBLE_HEX \
 -     "16#%" HOST_LONG_FORMAT "x%08" HOST_LONG_FORMAT "x#"
 -# endif
 -#else
 -  /* We can assume that 'long long' is at least 64 bits.  */
 -# define ADA_HOST_WIDE_INT_PRINT_DOUBLE_HEX \
 -    "16#%" HOST_LONG_LONG_FORMAT "x%016" HOST_LONG_LONG_FORMAT "x#"
 -#endif /* HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG */
 +#include "wide-int.h"
  
  /* Local functions, macros and variables.  */
- static int dump_generic_ada_node (pretty_printer *, tree, tree,
-                                 int (*)(tree, cpp_operation), int, int, bool);
- static int print_ada_declaration (pretty_printer *, tree, tree,
-                                 int (*cpp_check)(tree, cpp_operation), int);
- static void print_ada_struct_decl (pretty_printer *, tree, tree,
-                                  int (*cpp_check)(tree, cpp_operation), int,
-                                  bool);
+ static int dump_generic_ada_node (pretty_printer *, tree, tree, int, int,
+                                 bool);
+ static int print_ada_declaration (pretty_printer *, tree, tree, int);
+ static void print_ada_struct_decl (pretty_printer *, tree, tree, int, bool);
  static void dump_sloc (pretty_printer *buffer, tree node);
  static void print_comment (pretty_printer *, const char *);
- static void print_generic_ada_decl (pretty_printer *, tree,
-                                   int (*)(tree, cpp_operation), const char *);
+ static void print_generic_ada_decl (pretty_printer *, tree, const char *);
  static char *get_ada_package (const char *);
- static void dump_ada_nodes (pretty_printer *, const char *,
-                           int (*)(tree, cpp_operation));
+ static void dump_ada_nodes (pretty_printer *, const char *);
  static void reset_ada_withs (void);
  static void dump_ada_withs (FILE *);
  static void dump_ads (const char *, void (*)(const char *),
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,f719d5518699a9f529278c5d38e9612905a03532..1fde1c549c26b6b642dddafd7673f801849c41a2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1305 +1,1305 @@@
 -      && INT_CST_LT_UNSIGNED (TYPE_SIZE (var_type),
 -                            TYPE_SIZE (integer_type_node)))
+ /* This file is part of the Intel(R) Cilk(TM) Plus support
+    This file contains the CilkPlus Intrinsics
+    Copyright (C) 2013 Free Software Foundation, Inc.
+    Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+    Intel Corporation
+ This file is part of GCC.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tree.h"
+ #include "langhooks.h"
+ #include "gimple.h"
+ #include "tree-iterator.h"
+ #include "tree-inline.h"
+ #include "c-family/c-common.h"
+ #include "toplev.h" 
+ #include "cgraph.h"
+ #include "diagnostic.h"
+ #include "cilk.h"
+ enum add_variable_type {
+     /* Reference to previously-defined variable.  */
+     ADD_READ,
+     /* Definition of a new variable in inner-scope.  */
+     ADD_BIND,
+     /* Write to possibly previously-defined variable.  */
+     ADD_WRITE
+ };
+ enum cilk_block_type {
+     /* Indicates a _Cilk_spawn block.  30 was an arbitary number picked for 
+        ease of debugging.  */
+     CILK_BLOCK_SPAWN = 30,
+     /* Indicates _Cilk_for statement block.  */
+     CILK_BLOCK_FOR
+ };
+ struct wrapper_data
+ {
+   /* Kind of function to be created.  */
+   enum cilk_block_type type;
+   /* Signature of helper function.  */
+   tree fntype;
+   /* Containing function.  */
+   tree context;
+   /* Disposition of all variables in the inner statement.  */
+   struct pointer_map_t *decl_map;
+   /* True if this function needs a static chain.  */
+   bool nested;
+   /* Arguments to be passed to wrapper function, currently a list.  */
+   tree arglist;
+   /* Argument types, a list.  */
+   tree argtypes;
+   /* Incoming parameters.  */
+   tree parms;
+   /* Outer BLOCK object.  */
+   tree block;
+ };
+ static void extract_free_variables (tree, struct wrapper_data *,
+                                   enum add_variable_type);
+ static HOST_WIDE_INT cilk_wrapper_count;
+ /* Marks the CALL_EXPR or FUNCTION_DECL, FCALL, as a spawned function call
+    and the current function as a spawner.  Emit error if the function call
+    is outside a function or if a non function-call is spawned.  */
+ inline bool
+ cilk_set_spawn_marker (location_t loc, tree fcall)
+ {
+   if (!current_function_decl)
+     {
+       error_at (loc, "%<_Cilk_spawn%> may only be used inside a function");
+       return false;
+     }
+   else if (fcall == error_mark_node)
+     /* Error reporting here is not necessary here since if FCALL is an
+        error_mark_node, the function marking it as error would have reported
+        it.  */
+     return false; 
+   else if (TREE_CODE (fcall) != CALL_EXPR
+          && TREE_CODE (fcall) != FUNCTION_DECL
+          /* In C++, TARGET_EXPR is generated when we have an overloaded
+             '=' operator.  */
+          && TREE_CODE (fcall) != TARGET_EXPR)
+     { 
+       error_at (loc, "only function calls can be spawned");
+       return false;
+     }
+   else
+     {
+       cfun->calls_cilk_spawn = true;
+       return true;
+     }
+ }
+ /* This function will output the exit conditions for a spawn call.  */
+ tree
+ create_cilk_function_exit (tree frame, bool detaches, bool needs_sync)
+ {
+   tree epi = alloc_stmt_list ();
+   if (needs_sync) 
+     append_to_statement_list (build_cilk_sync (), &epi);
+   tree func_ptr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
+   tree pop_frame = build_call_expr (cilk_pop_fndecl, 1, func_ptr);
+   tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, 0);
+   tree current = cilk_arrow (worker, CILK_TI_WORKER_CUR, 0);
+   tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
+   tree set_current = build2 (MODIFY_EXPR, void_type_node, current, parent);
+   append_to_statement_list (set_current, &epi);
+   append_to_statement_list (pop_frame, &epi);
+   tree call = build_call_expr (cilk_leave_fndecl, 1, func_ptr);
+   if (!detaches)
+     {
+       tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
+       tree flags_cmp_expr = fold_build2 (NE_EXPR, TREE_TYPE (flags), flags, 
+                                        build_int_cst (TREE_TYPE (flags), 
+                                                       CILK_FRAME_VERSION));
+       call = fold_build3 (COND_EXPR, void_type_node, flags_cmp_expr,
+                         call, build_empty_stmt (EXPR_LOCATION (flags)));
+     }
+   append_to_statement_list (call, &epi);  
+   return epi;
+ }
+ /* Trying to get the correct cfun for the FUNCTION_DECL indicated by OUTER.  */
+ static void
+ pop_cfun_to (tree outer)
+ {
+   pop_cfun ();
+   current_function_decl = outer;
+   gcc_assert (cfun == DECL_STRUCT_FUNCTION (current_function_decl));
+   gcc_assert (cfun->decl == current_function_decl);
+ }
+ /* This function does whatever is necessary to make the compiler emit a newly 
+    generated function, FNDECL.  */
+ static void
+ call_graph_add_fn (tree fndecl)
+ {
+   const tree outer = current_function_decl;
+   struct function *f = DECL_STRUCT_FUNCTION (fndecl);
+   gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
+   f->is_cilk_function = 1;
+   f->curr_properties = cfun->curr_properties;
+   gcc_assert (cfun == DECL_STRUCT_FUNCTION (outer)); 
+   gcc_assert (cfun->decl == outer);
+   push_cfun (f);
+   cgraph_create_node (fndecl);
+   pop_cfun_to (outer);
+ }
+ /* Return true if this is a tree which is allowed to contain a spawn as 
+    operand 0.
+    A spawn call may be wrapped in a series of unary operations such
+    as conversions.  These conversions need not be "useless"
+    to be disregarded because they are retained in the spawned
+    statement.  They are bypassed only to look for a spawn
+    within.
+    A comparison to constant is simple enough to allow, and
+    is used to convert to bool.  */
+ static bool
+ cilk_ignorable_spawn_rhs_op (tree exp)
+ {
+   enum tree_code code = TREE_CODE (exp);
+   switch (TREE_CODE_CLASS (code))
+     {
+     case tcc_expression:
+       return code == ADDR_EXPR;
+     case tcc_comparison:
+       /* We need the spawn as operand 0 for now.   That's where it
+        appears in the only case we really care about, conversion
+        to bool.  */
+       return (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST);
+     case tcc_unary:
+     case tcc_reference:
+       return true;
+     default:
+       return false;
+     }
+ }
+ /* Helper function for walk_tree.  If *TP is a CILK_SPAWN_STMT, then unwrap
+    this "wrapper."  The function returns NULL_TREE regardless.  */
+ static tree
+ unwrap_cilk_spawn_stmt (tree *tp, int *walk_subtrees, void *)
+ {
+   if (TREE_CODE (*tp) == CILK_SPAWN_STMT)
+     {
+       *tp = CILK_SPAWN_FN (*tp);
+       *walk_subtrees = 0;
+     }
+   return NULL_TREE;
+ }
+ /* Returns true when EXP is a CALL_EXPR with _Cilk_spawn in front.  Unwraps
+    CILK_SPAWN_STMT wrapper from the CALL_EXPR in *EXP0 statement.  */
+ static bool
+ recognize_spawn (tree exp, tree *exp0)
+ {
+   bool spawn_found = false;
+   if (TREE_CODE (exp) == CILK_SPAWN_STMT)
+     {
+       /* Remove the CALL_EXPR from CILK_SPAWN_STMT wrapper.  */
+       exp = CILK_SPAWN_FN (exp);
+       walk_tree (exp0, unwrap_cilk_spawn_stmt, NULL, NULL);
+       spawn_found = true;
+     }
+   return spawn_found;
+ }
+ /* Returns true if *EXP0 is a recognized form of spawn.  Recognized forms are,
+    after conversion to void, a call expression at outer level or an assignment
+    at outer level with the right hand side being a spawned call.
+    In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the
+    CALL_EXPR that is being spawned.
+    Note that `=' in C++ may turn into a CALL_EXPR rather than a MODIFY_EXPR.  */
+ bool
+ cilk_detect_spawn_and_unwrap (tree *exp0)
+ {
+   tree exp = *exp0;
+   if (!TREE_SIDE_EFFECTS (exp))
+     return false;
+   /* Strip off any conversion to void.  It does not affect whether spawn 
+      is supported here.  */
+   if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp)))
+     exp = TREE_OPERAND (exp, 0);
+   if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR)
+     exp = TREE_OPERAND (exp, 1);
+   while (cilk_ignorable_spawn_rhs_op (exp))
+     exp = TREE_OPERAND (exp, 0);
+   if (TREE_CODE (exp) == TARGET_EXPR)
+     if (TARGET_EXPR_INITIAL (exp)
+       && TREE_CODE (TARGET_EXPR_INITIAL (exp)) != AGGR_INIT_EXPR)
+       exp = TARGET_EXPR_INITIAL (exp);
+   /* Happens with C++ TARGET_EXPR.  */
+   if (exp == NULL_TREE)
+     return false;
+   while (TREE_CODE (exp) == CLEANUP_POINT_EXPR || TREE_CODE (exp) == EXPR_STMT)
+     exp = TREE_OPERAND (exp, 0);
+   
+   /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around 
+      it, or return false.  */
+   if (recognize_spawn (exp, exp0))
+     return true;
+   return false;
+ }
+ /* This function will build and return a FUNCTION_DECL using information 
+    from *WD.  */
+ static tree
+ create_cilk_helper_decl (struct wrapper_data *wd)
+ {
+   char name[20];
+   if (wd->type == CILK_BLOCK_FOR)
+     sprintf (name, "_cilk_for_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
+   else if (wd->type == CILK_BLOCK_SPAWN)
+     sprintf (name, "_cilk_spn_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
+   else
+     gcc_unreachable (); 
+   
+   clean_symbol_name (name);
+   tree fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, 
+                           get_identifier (name), wd->fntype);
+   TREE_PUBLIC (fndecl) = 0;
+   TREE_STATIC (fndecl) = 1;
+   TREE_USED (fndecl) = 1;
+   DECL_ARTIFICIAL (fndecl) = 0;
+   DECL_IGNORED_P (fndecl) = 0;
+   DECL_EXTERNAL (fndecl) = 0;
+   DECL_CONTEXT (fndecl) = wd->context; 
+   tree block = make_node (BLOCK);
+   DECL_INITIAL (fndecl) = block;
+   TREE_USED (block) = 1;
+   gcc_assert (!DECL_SAVED_TREE (fndecl));
+   /* Inlining would defeat the purpose of this wrapper.
+      Either it secretly switches stack frames or it allocates
+      a stable stack frame to hold function arguments even if
+      the parent stack frame is stolen.  */
+   DECL_UNINLINABLE (fndecl) = 1;
+   tree result_decl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, 
+                                void_type_node);
+   DECL_ARTIFICIAL (result_decl) = 0;
+   DECL_IGNORED_P (result_decl) = 1;
+   DECL_CONTEXT (result_decl) = fndecl;
+   DECL_RESULT (fndecl) = result_decl;
+   
+   return fndecl;
+ }
+ /* A function used by walk tree to find wrapper parms.  */
+ static bool
+ wrapper_parm_cb (const void *key0, void **val0, void *data)
+ {
+   struct wrapper_data *wd = (struct wrapper_data *) data;
+   tree arg = * (tree *)&key0;
+   tree val = (tree)*val0;
+   tree parm;
+   if (val == error_mark_node || val == arg)
+     return true;
+   if (TREE_CODE (val) == PAREN_EXPR)
+     {
+       /* We should not reach here with a register receiver.
+        We may see a register variable modified in the
+        argument list.  Because register variables are
+        worker-local we don't need to work hard to support
+        them in code that spawns.  */
+       if ((TREE_CODE (arg) == VAR_DECL) && DECL_HARD_REGISTER (arg))
+       {
+         error_at (EXPR_LOCATION (arg),
+                   "explicit register variable %qD may not be modified in "
+                   "spawn", arg);
+         arg = null_pointer_node;
+       }
+       else
+       arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), arg);
+       
+       val = TREE_OPERAND (val, 0);
+       *val0 = val;
+       gcc_assert (TREE_CODE (val) == INDIRECT_REF);
+       parm = TREE_OPERAND (val, 0);
+       STRIP_NOPS (parm);
+     }
+   else
+     parm = val;
+   TREE_CHAIN (parm) = wd->parms;
+   wd->parms = parm;
+   wd->argtypes = tree_cons (NULL_TREE, TREE_TYPE (parm), wd->argtypes); 
+   wd->arglist = tree_cons (NULL_TREE, arg, wd->arglist); 
+   return true;
+ }
+ /* This function is used to build a wrapper of a certain type.  */
+ static void
+ build_wrapper_type (struct wrapper_data *wd)
+ {
+   wd->arglist = NULL_TREE;
+   wd->parms = NULL_TREE;
+   wd->argtypes = void_list_node;
+   pointer_map_traverse (wd->decl_map, wrapper_parm_cb, wd);
+   gcc_assert (wd->type != CILK_BLOCK_FOR);
+   /* Now build a function.
+      Its return type is void (all side effects are via explicit parameters).
+      Its parameters are WRAPPER_PARMS with type WRAPPER_TYPES.
+      Actual arguments in the caller are WRAPPER_ARGS.  */
+   wd->fntype = build_function_type (void_type_node, wd->argtypes);
+ }
+ /* This function checks all the CALL_EXPRs in *TP found by cilk_outline.  */
+ static tree
+ check_outlined_calls (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, 
+                     void *data)
+ {
+   bool *throws = (bool *) data;
+   tree t = *tp;
+   int flags;
+   if (TREE_CODE (t) != CALL_EXPR)
+     return 0;
+   flags = call_expr_flags (t);
+   if (!(flags & ECF_NOTHROW) && flag_exceptions)
+     *throws = true;
+   if (flags & ECF_RETURNS_TWICE)
+     error_at (EXPR_LOCATION (t), 
+             "cannot spawn call to function that returns twice");
+   return 0;
+ }
+ /* Each DECL in the source code (spawned statement) is passed to this function
+    once.  Each instance of the DECL is replaced with the result of this 
+    function.
+    The parameters of the wrapper should have been entered into the map already.
+    This function only deals with variables with scope limited to the 
+    spawned expression.  */
+ static tree
+ copy_decl_for_cilk (tree decl, copy_body_data *id)
+ {
+   switch (TREE_CODE (decl))
+     {
+     case VAR_DECL:
+       return copy_decl_no_change (decl, id);
+     case LABEL_DECL:
+       error_at (EXPR_LOCATION (decl), "invalid use of label %q+D in "
+               "%<_Cilk_spawn%>", 
+               decl);
+       return error_mark_node;
+     case RESULT_DECL:
+     case PARM_DECL:
+       /* RESULT_DECL and PARM_DECL has already been entered into the map.  */
+     default:
+       gcc_unreachable ();
+       return error_mark_node;
+     }
+ }
+ /* Copy all local variables.  */
+ static bool
+ for_local_cb (const void *k_v, void **vp, void *p)
+ {
+   tree k = *(tree *) &k_v;
+   tree v = (tree) *vp;
+   if (v == error_mark_node)
+     *vp = copy_decl_no_change (k, (copy_body_data *) p);
+   return true;
+ }
+ /* Copy all local declarations from a _Cilk_spawned function's body.  */
+ static bool
+ wrapper_local_cb (const void *k_v, void **vp, void *data)
+ {
+   copy_body_data *id = (copy_body_data *) data;
+   tree key = *(tree *) &k_v;
+   tree val = (tree) *vp;
+   if (val == error_mark_node)
+     *vp = copy_decl_for_cilk (key, id);
+   return true;
+ }
+ /* Alter a tree STMT from OUTER_FN to form the body of INNER_FN.  */
+ static void
+ cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd)
+ {
+   const tree outer_fn = wd->context;        
+   const bool nested = (wd->type == CILK_BLOCK_FOR);
+   copy_body_data id;
+   bool throws;
+   DECL_STATIC_CHAIN (outer_fn) = 1;
+   memset (&id, 0, sizeof (id));
+   /* Copy from the function containing the spawn...  */
+   id.src_fn = outer_fn;
+   /* ...to the wrapper.  */
+   id.dst_fn = inner_fn; 
+   id.src_cfun = DECL_STRUCT_FUNCTION (outer_fn);
+   /* There shall be no RETURN in spawn helper.  */
+   id.retvar = 0; 
+   id.decl_map = wd->decl_map;
+   id.copy_decl = nested ? copy_decl_no_change : copy_decl_for_cilk;
+   id.block = DECL_INITIAL (inner_fn);
+   id.transform_lang_insert_block = NULL;
+   id.transform_new_cfg = true;
+   id.transform_call_graph_edges = CB_CGE_MOVE;
+   id.remap_var_for_cilk = true;
+   id.regimplify = true; /* unused? */
+   insert_decl_map (&id, wd->block, DECL_INITIAL (inner_fn));
+   /* We don't want the private variables any more.  */
+   pointer_map_traverse (wd->decl_map, nested ? for_local_cb : wrapper_local_cb,
+                       &id);
+   walk_tree (stmt_p, copy_tree_body_r, &id, NULL);
+   /* See if this function can throw or calls something that should
+      not be spawned.  The exception part is only necessary if
+      flag_exceptions && !flag_non_call_exceptions.  */
+   throws = false ;
+   (void) walk_tree_without_duplicates (stmt_p, check_outlined_calls, &throws);
+ }
+ /* Generate the body of a wrapper function that assigns the
+    result of the expression RHS into RECEIVER.  RECEIVER must
+    be NULL if this is not a spawn -- the wrapper will return
+    a value.  If this is a spawn, the wrapper will return void.  */
+ static tree
+ create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd)
+ {
+   const tree outer = current_function_decl;
+   tree fndecl;
+   tree p;
+    /* Build the type of the wrapper and its argument list from the
+      variables that it requires.  */
+   build_wrapper_type (wd);
+   /* Emit a function that takes WRAPPER_PARMS incoming and applies ARGS 
+      (modified) to the wrapped function.  Return the wrapper and modified ARGS 
+      to the caller to generate a function call.  */
+   fndecl = create_cilk_helper_decl (wd);
+   push_struct_function (fndecl);
+   if (wd->nested && (wd->type == CILK_BLOCK_FOR))
+     {
+       gcc_assert (TREE_VALUE (wd->arglist) == NULL_TREE);
+       TREE_VALUE (wd->arglist) = build2 (FDESC_EXPR, ptr_type_node,
+                                        fndecl, integer_one_node);
+     }
+   DECL_ARGUMENTS (fndecl) = wd->parms;
+   for (p = wd->parms; p; p = TREE_CHAIN (p))
+     DECL_CONTEXT (p) = fndecl;
+   cilk_outline (fndecl, &stmt, wd);
+   stmt = fold_build_cleanup_point_expr (void_type_node, stmt);
+   gcc_assert (!DECL_SAVED_TREE (fndecl));
+   lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, stmt);
+   gcc_assert (DECL_SAVED_TREE (fndecl));
+   pop_cfun_to (outer);
+   /* Recognize the new function.  */
+   call_graph_add_fn (fndecl);
+   return fndecl;
+ }
+ /* Initializes the wrapper data structure.  */
+ static void
+ init_wd (struct wrapper_data *wd, enum cilk_block_type type)
+ {
+   wd->type = type;
+   wd->fntype = NULL_TREE;
+   wd->context = current_function_decl;
+   wd->decl_map = pointer_map_create ();
+   /* _Cilk_for bodies are always nested.  Others start off as 
+      normal functions.  */
+   wd->nested = (type == CILK_BLOCK_FOR);
+   wd->arglist = NULL_TREE;
+   wd->argtypes = NULL_TREE;
+   wd->block = NULL_TREE;
+ }
+ /* Clears the wrapper data structure.  */
+ static void
+ free_wd (struct wrapper_data *wd)
+ {
+   pointer_map_destroy (wd->decl_map);
+   wd->nested = false;
+   wd->arglist = NULL_TREE;
+   wd->argtypes = NULL_TREE;
+   wd->parms = NULL_TREE;
+ }
+  /* Given a variable in an expression to be extracted into
+    a helper function, declare the helper function parameter
+    to receive it.
+    On entry the value of the (key, value) pair may be
+    (*, error_mark_node) -- Variable is private to helper function,
+    do nothing.
+    (var, var) -- Reference to outer scope (function or global scope).
+    (var, integer 0) -- Capture by value, save newly-declared PARM_DECL
+    for value in value slot.
+    (var, integer 1) -- Capture by reference, declare pointer to type
+    as new PARM_DECL and store (spawn_stmt (indirect_ref (parm)).
+    
+    (var, ???) -- Pure output argument, handled similarly to above.
+ */
+ static bool
+ declare_one_free_variable (const void *var0, void **map0,
+                          void *data ATTRIBUTE_UNUSED)
+ {
+   const_tree var = (const_tree) var0;
+   tree map = (tree)*map0;
+   tree var_type = TREE_TYPE (var), arg_type;
+   bool by_reference;
+   tree parm;
+   gcc_assert (DECL_P (var));
+   /* Ignore truly local variables.  */
+   if (map == error_mark_node)
+     return true;
+   /* Ignore references to the parent function.  */
+   if (map == var)
+     return true;
+   gcc_assert (TREE_CODE (map) == INTEGER_CST);
+   /* A value is passed by reference if:
+      1. It is addressable, so that a copy may not be made.
+      2. It is modified in the spawned statement.
+      In the future this function may want to arrange
+      a warning if the spawned statement is a loop body
+      because an output argument would indicate a race.
+      Note: Earlier passes must have marked the variable addressable.
+      3. It is expensive to copy.  */
+   by_reference =
+     (TREE_ADDRESSABLE (var_type)
+      /* Arrays must be passed by reference.  This is required for C
+       semantics -- arrays are not first class objects.  Other
+       aggregate types can and should be passed by reference if
+       they are not passed to the spawned function.  We aren't yet
+       distinguishing safe uses in argument calculation from unsafe
+       uses as outgoing function arguments, so we make a copy to
+       stabilize the value.  */
+      || TREE_CODE (var_type) == ARRAY_TYPE
+      || (tree) map == integer_one_node);
+   if (by_reference)
+     var_type = build_qualified_type (build_pointer_type (var_type),
+                                    TYPE_QUAL_RESTRICT);
+   gcc_assert (!TREE_ADDRESSABLE (var_type));
+   /* Maybe promote to int.  */
+   if (INTEGRAL_TYPE_P (var_type) && COMPLETE_TYPE_P (var_type)
 -          len = TREE_INT_CST_LOW (TREE_OPERAND (t, 0));
++      && INT_CST_LT (TYPE_SIZE (var_type),
++                   TYPE_SIZE (integer_type_node)))
+     arg_type = integer_type_node;
+   else
+     arg_type = var_type;
+   parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE, var_type);
+   DECL_ARG_TYPE (parm) = arg_type;
+   DECL_ARTIFICIAL (parm) = 0;
+   TREE_READONLY (parm) = 1;
+   
+   if (by_reference)
+     {
+       parm = build1 (INDIRECT_REF, TREE_TYPE (var_type), parm);
+       parm = build1 (PAREN_EXPR, void_type_node, parm);
+     }
+   *map0 = parm;
+   return true;
+ }
+  
+ /* Returns a wrapper function for a _Cilk_spawn.  */
+ static tree
+ create_cilk_wrapper (tree exp, tree *args_out)
+ {
+   struct wrapper_data wd;
+   tree fndecl;
+   init_wd (&wd, CILK_BLOCK_SPAWN);
+   if (TREE_CODE (exp) == CONVERT_EXPR)
+     exp = TREE_OPERAND (exp, 0);
+   
+   /* Special handling for top level INIT_EXPR.  Usually INIT_EXPR means the 
+      variable is defined in the spawned expression and can be private to the 
+      spawn helper.  A top level INIT_EXPR defines a variable to be initialized 
+      by spawn and the variable must remain in the outer function.  */
+   if (TREE_CODE (exp) == INIT_EXPR)
+     {
+       extract_free_variables (TREE_OPERAND (exp, 0), &wd, ADD_WRITE);
+       extract_free_variables (TREE_OPERAND (exp, 1), &wd, ADD_READ);
+       /* TREE_TYPE should be void.  Be defensive.  */
+       if (TREE_TYPE (exp) != void_type_node)
+       extract_free_variables (TREE_TYPE (exp), &wd, ADD_READ);
+     }
+   else
+     extract_free_variables (exp, &wd, ADD_READ);
+   pointer_map_traverse (wd.decl_map, declare_one_free_variable, &wd);
+   wd.block = TREE_BLOCK (exp);
+   if (!wd.block)
+     wd.block = DECL_INITIAL (current_function_decl);
+   /* Now fvars maps the old variable to incoming variable.  Update
+      the expression and arguments to refer to the new names.  */
+   fndecl = create_cilk_wrapper_body (exp, &wd);
+   *args_out = wd.arglist;
+   
+   free_wd (&wd);
+   return fndecl;
+ }
+ /* Transform *SPAWN_P, a spawned CALL_EXPR, to gimple.  *SPAWN_P can be a
+    CALL_EXPR, INIT_EXPR or MODIFY_EXPR.  Returns GS_OK if everything is fine,
+    and GS_UNHANDLED, otherwise.  */
+ int
+ gimplify_cilk_spawn (tree *spawn_p, gimple_seq *before ATTRIBUTE_UNUSED,
+                    gimple_seq *after ATTRIBUTE_UNUSED)
+ {
+   tree expr = *spawn_p;
+   tree function, call1, call2, new_args;
+   tree ii_args = NULL_TREE;
+   int total_args = 0, ii = 0;
+   tree *arg_array;
+   tree setjmp_cond_expr = NULL_TREE;
+   tree setjmp_expr, spawn_expr, setjmp_value = NULL_TREE;
+   cfun->calls_cilk_spawn = 1;
+   cfun->is_cilk_function = 1;
+   /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p.  */
+   while (TREE_CODE (expr) == CLEANUP_POINT_EXPR
+        || TREE_CODE (expr) == EXPR_STMT)
+     expr = TREE_OPERAND (expr, 0);
+   
+   new_args = NULL;
+   function = create_cilk_wrapper (expr, &new_args);
+   /* This should give the number of parameters.  */
+   total_args = list_length (new_args);
+   arg_array = XNEWVEC (tree, total_args);
+   ii_args = new_args;
+   for (ii = 0; ii < total_args; ii++)
+     {
+       arg_array[ii] = TREE_VALUE (ii_args);
+       ii_args = TREE_CHAIN (ii_args);
+     }
+   
+   TREE_USED (function) = 1;
+   rest_of_decl_compilation (function, 0, 0);
+   call1 = cilk_call_setjmp (cfun->cilk_frame_decl);
+   if (*arg_array == NULL_TREE)
+     call2 = build_call_expr (function, 0);
+   else 
+     call2 = build_call_expr_loc_array (EXPR_LOCATION (*spawn_p), function, 
+                                        total_args, arg_array);
+   *spawn_p = alloc_stmt_list ();
+   tree f_ptr_type = build_pointer_type (TREE_TYPE (cfun->cilk_frame_decl));
+   tree frame_ptr = build1 (ADDR_EXPR, f_ptr_type, cfun->cilk_frame_decl);
+   tree save_fp = build_call_expr (cilk_save_fp_fndecl, 1, frame_ptr);
+   append_to_statement_list (save_fp, spawn_p);                  
+   setjmp_value = create_tmp_var (TREE_TYPE (call1), NULL);
+   setjmp_expr = fold_build2 (MODIFY_EXPR, void_type_node, setjmp_value, call1);
+   append_to_statement_list_force (setjmp_expr, spawn_p);
+   
+   setjmp_cond_expr = fold_build2 (EQ_EXPR, TREE_TYPE (call1), setjmp_value,
+                                 build_int_cst (TREE_TYPE (call1), 0));
+   spawn_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_cond_expr,
+                           call2, build_empty_stmt (EXPR_LOCATION (call1)));
+   append_to_statement_list (spawn_expr, spawn_p);
+   return GS_OK;
+ }
+ /* Make the frames necessary for a spawn call.  */
+ tree
+ make_cilk_frame (tree fn)
+ {
+   struct function *f = DECL_STRUCT_FUNCTION (fn);
+   tree decl;
+   if (f->cilk_frame_decl)
+     return f->cilk_frame_decl;
+   decl = build_decl (EXPR_LOCATION (fn), VAR_DECL, NULL_TREE, 
+                    cilk_frame_type_decl);
+   DECL_CONTEXT (decl) = fn;
+   DECL_SEEN_IN_BIND_EXPR_P (decl) = 1;
+   f->cilk_frame_decl = decl;
+   return decl;
+ }
+ /* Returns a STATEMENT_LIST with all the pedigree operations required for
+    install body with frame cleanup functions.  FRAME_PTR is the pointer to
+    __cilkrts_stack_frame created by make_cilk_frame.  */
+ tree
+ cilk_install_body_pedigree_operations (tree frame_ptr)
+ {
+   tree body_list = alloc_stmt_list ();
+   tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, frame_ptr); 
+   append_to_statement_list (enter_frame, &body_list);
+   
+   tree parent = cilk_arrow (frame_ptr, CILK_TI_FRAME_PARENT, 0);
+   tree worker = cilk_arrow (frame_ptr, CILK_TI_FRAME_WORKER, 0);
+   tree pedigree = cilk_arrow (frame_ptr, CILK_TI_FRAME_PEDIGREE, 0);
+   tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0);
+   tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0);
+   tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0);
+   tree pedigree_parent_rank = cilk_dot (pedigree_parent, 
+                                       CILK_TI_PEDIGREE_RANK, 0);
+   tree pedigree_parent_parent = cilk_dot (pedigree_parent, 
+                                    CILK_TI_PEDIGREE_PARENT, 0);
+   tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1);
+   tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0);
+   tree w_pedigree_parent = cilk_dot (worker_pedigree, 
+                                    CILK_TI_PEDIGREE_PARENT, 0);
+   /* sf.pedigree.rank = worker->pedigree.rank.  */
+   tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank,
+                    w_pedigree_rank);
+   append_to_statement_list (exp1, &body_list);
+   /* sf.pedigree.parent = worker->pedigree.parent.  */
+   exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree,
+                w_pedigree_parent);
+   append_to_statement_list (exp1, &body_list);
+   /* sf.call_parent->pedigree.rank = worker->pedigree.rank.  */
+   exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank,
+                w_pedigree_rank);
+   append_to_statement_list (exp1, &body_list);
+   /* sf.call_parent->pedigree.parent = worker->pedigree.parent.  */
+   exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent,
+                w_pedigree_parent);
+   append_to_statement_list (exp1, &body_list);
+   /* sf->worker.pedigree.rank = 0.  */
+   exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank, 
+                build_zero_cst (uint64_type_node));
+   append_to_statement_list (exp1, &body_list);
+   /* sf->pedigree.parent = &sf->pedigree.  */
+   exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent,
+                build1 (ADDR_EXPR,
+                        build_pointer_type (cilk_pedigree_type_decl),
+                        pedigree));
+   append_to_statement_list (exp1, &body_list);
+   return body_list;
+ }
+ /* Inserts "cleanup" functions after the function-body of FNDECL.  FNDECL is a 
+    spawn-helper and BODY is the newly created body for FNDECL.  */
+ void
+ c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body)
+ {
+   tree list = alloc_stmt_list ();
+   tree frame = make_cilk_frame (fndecl);
+   tree dtor = create_cilk_function_exit (frame, false, true);
+   add_local_decl (cfun, frame);
+   
+   DECL_SAVED_TREE (fndecl) = list;
+   tree frame_ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), 
+                          frame);
+   tree body_list = cilk_install_body_pedigree_operations (frame_ptr);
+   gcc_assert (TREE_CODE (body_list) == STATEMENT_LIST);
+   
+   tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, frame_ptr); 
+   append_to_statement_list (detach_expr, &body_list);
+   append_to_statement_list (body, &body_list);
+   append_to_statement_list (build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR,
+                                       body_list, dtor), &list);
+ }
+ /* Add a new variable, VAR to a variable list in WD->DECL_MAP.  HOW indicates
+    whether the variable is previously defined, currently defined, or a variable 
+    that is being written to.  */
+ static void
+ add_variable (struct wrapper_data *wd, tree var, enum add_variable_type how)
+ {
+   void **valp;
+   
+   valp = pointer_map_contains (wd->decl_map, (void *) var);
+   if (valp)
+     {
+       tree val = (tree) *valp;
+       /* If the variable is local, do nothing.  */
+       if (val == error_mark_node)
+       return;
+       /* If the variable was entered with itself as value,
+        meaning it belongs to an outer scope, do not alter
+        the value.  */
+       if (val == var) 
+       return;
+       /* A statement expression may cause a variable to be
+        bound twice, once in BIND_EXPR and again in a
+        DECL_EXPR.  That case caused a return in the 
+        test above.  Any other duplicate definition is
+        an error.  */
+       gcc_assert (how != ADD_BIND);
+       if (how != ADD_WRITE)
+       return;
+       /* This variable might have been entered as read but is now written.  */
+       *valp = (void *) var;
+       wd->nested = true;
+       return;
+     }
+   else
+     {
+       tree val = NULL_TREE;
+       /* Nested function rewriting silently discards hard register
+        assignments for function scope variables, and they wouldn't
+        work anyway.  Warn here.  This misses one case: if the
+        register variable is used as the loop bound or increment it
+        has already been added to the map.  */
+       if ((how != ADD_BIND) && (TREE_CODE (var) == VAR_DECL)
+         && !DECL_EXTERNAL (var) && DECL_HARD_REGISTER (var))
+       warning (0, "register assignment ignored for %qD used in Cilk block",
+                var);
+       switch (how)
+       {
+         /* ADD_BIND means always make a fresh new variable.  */
+       case ADD_BIND:
+         val = error_mark_node;
+         break;
+         /* ADD_READ means
+            1. For cilk_for, refer to the outer scope definition as-is
+            2. For a spawned block, take a scalar in an rgument
+            and otherwise refer to the outer scope definition as-is.
+            3. For a spawned call, take a scalar in an argument.  */
+       case ADD_READ:
+         switch (wd->type)
+           {
+           case CILK_BLOCK_FOR:
+             val = var;
+             break;
+           case CILK_BLOCK_SPAWN:
+             if (TREE_ADDRESSABLE (var))
+               {
+                 val = var;
+                 wd->nested = true;
+                 break;
+               }
+             val = integer_zero_node;
+             break;
+           }
+         break;
+       case ADD_WRITE:
+         switch (wd->type)
+           {
+           case CILK_BLOCK_FOR:
+             val = var;
+             wd->nested = true;
+             break;
+           case CILK_BLOCK_SPAWN:
+             if (TREE_ADDRESSABLE (var))
+               val = integer_one_node;
+             else
+               {
+                 val = var;
+                 wd->nested = true;
+               }
+             break;
+           }
+       }
+       *pointer_map_insert (wd->decl_map, (void *) var) = val;
+     }
+ }
+ /* Find the variables referenced in an expression T.  This does not avoid 
+    duplicates because a variable may be read in one context and written in 
+    another.  HOW describes the context in which the reference is seen.  If 
+    NESTED is true a nested function is being generated and variables in the 
+    original context should not be remapped.  */
+ static void
+ extract_free_variables (tree t, struct wrapper_data *wd,
+                       enum add_variable_type how)
+ {  
+   if (t == NULL_TREE)
+     return;
+   enum tree_code code = TREE_CODE (t);
+   bool is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code));
+   if (is_expr)
+     extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+   switch (code)
+     {
+     case ERROR_MARK:
+     case IDENTIFIER_NODE:
+     case INTEGER_CST:
+     case REAL_CST:
+     case FIXED_CST:
+     case STRING_CST:
+     case BLOCK:
+     case PLACEHOLDER_EXPR:
+     case FIELD_DECL:
+     case VOID_TYPE:
+     case REAL_TYPE:
+       /* These do not contain variable references.  */
+       return;
+     case SSA_NAME:
+       /* Currently we don't see SSA_NAME.  */
+       extract_free_variables (SSA_NAME_VAR (t), wd, how);
+       return;
+     case LABEL_DECL:
+       /* This might be a reference to a label outside the Cilk block,
+        which is an error, or a reference to a label in the Cilk block
+        that we haven't seen yet.  We can't tell.  Ignore it.  An
+        invalid use will cause an error later in copy_decl_for_cilk.  */
+       return;
+     case RESULT_DECL:
+       if (wd->type != CILK_BLOCK_SPAWN)
+       TREE_ADDRESSABLE (t) = 1;
+     case VAR_DECL:
+     case PARM_DECL:
+       if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
+       add_variable (wd, t, how);
+       return;
+     case NON_LVALUE_EXPR:
+     case CONVERT_EXPR:
+     case NOP_EXPR:
+       extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
+       return;
+     case INIT_EXPR:
+       extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
+       extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+       return;
+     case MODIFY_EXPR:
+     case PREDECREMENT_EXPR:
+     case PREINCREMENT_EXPR:
+     case POSTDECREMENT_EXPR:
+     case POSTINCREMENT_EXPR:
+       /* These write their result.  */
+       extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
+       extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+       return;
+     case ADDR_EXPR:
+       /* This might modify its argument, and the value needs to be
+        passed by reference in any case to preserve identity and
+        type if is a promoting type.  In the case of a nested loop
+        just notice that we touch the variable.  It will already
+        be addressable, and marking it modified will cause a spurious
+        warning about writing the control variable.  */
+       if (wd->type != CILK_BLOCK_SPAWN)
+       extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
+       else 
+       extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
+       return;
+     case ARRAY_REF:
+       /* Treating ARRAY_REF and BIT_FIELD_REF identically may
+        mark the array as written but the end result is correct
+        because the array is passed by pointer anyway.  */
+     case BIT_FIELD_REF:
+       /* Propagate the access type to the object part of which
+        is being accessed here.  As for ADDR_EXPR, don't do this
+        in a nested loop, unless the access is to a fixed index.  */
+       if (wd->type != CILK_BLOCK_FOR || TREE_CONSTANT (TREE_OPERAND (t, 1)))
+       extract_free_variables (TREE_OPERAND (t, 0), wd, how);
+       else
+       extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
+       extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+       extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
+       return;
+     case TREE_LIST:
+       extract_free_variables (TREE_PURPOSE (t), wd, ADD_READ);
+       extract_free_variables (TREE_VALUE (t), wd, ADD_READ);
+       extract_free_variables (TREE_CHAIN (t), wd, ADD_READ);
+       return;
+     case TREE_VEC:
+       {
+       int len = TREE_VEC_LENGTH (t);
+       int i;
+       for (i = 0; i < len; i++)
+         extract_free_variables (TREE_VEC_ELT (t, i), wd, ADD_READ);
+       return;
+       }
+     case VECTOR_CST:
+       {
+       unsigned ii = 0;
+       for (ii = 0; ii < VECTOR_CST_NELTS (t); ii++)
+         extract_free_variables (VECTOR_CST_ELT (t, ii), wd, ADD_READ); 
+       break;
+       }
+     case COMPLEX_CST:
+       extract_free_variables (TREE_REALPART (t), wd, ADD_READ);
+       extract_free_variables (TREE_IMAGPART (t), wd, ADD_READ);
+       return;
+     case BIND_EXPR:
+       {
+       tree decl;
+       for (decl = BIND_EXPR_VARS (t); decl; decl = TREE_CHAIN (decl))
+         {
+           add_variable (wd, decl, ADD_BIND);
+           /* A self-referential initialization is no problem because
+              we already entered the variable into the map as local.  */
+           extract_free_variables (DECL_INITIAL (decl), wd, ADD_READ);
+           extract_free_variables (DECL_SIZE (decl), wd, ADD_READ);
+           extract_free_variables (DECL_SIZE_UNIT (decl), wd, ADD_READ);
+         }
+       extract_free_variables (BIND_EXPR_BODY (t), wd, ADD_READ);
+       return;
+       }
+     case STATEMENT_LIST:
+       {
+       tree_stmt_iterator i;
+       for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+         extract_free_variables (*tsi_stmt_ptr (i), wd, ADD_READ);
+       return;
+       }
+     case TARGET_EXPR:
+       {
+       extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
+       extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+       extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
+       if (TREE_OPERAND (t, 3) != TREE_OPERAND (t, 1))
+         extract_free_variables (TREE_OPERAND (t, 3), wd, ADD_READ);
+       return;
+       }
+     case RETURN_EXPR:
+       if (TREE_NO_WARNING (t))
+       {
+         gcc_assert (errorcount);
+         return;
+       }
+       return;
+     case DECL_EXPR:
+       if (TREE_CODE (DECL_EXPR_DECL (t)) != TYPE_DECL)
+       extract_free_variables (DECL_EXPR_DECL (t), wd, ADD_BIND);
+       return;
+     case INTEGER_TYPE:
+     case ENUMERAL_TYPE:
+     case BOOLEAN_TYPE:
+       extract_free_variables (TYPE_MIN_VALUE (t), wd, ADD_READ);
+       extract_free_variables (TYPE_MAX_VALUE (t), wd, ADD_READ);
+       return;
+     case POINTER_TYPE:
+       extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+       break;
+     case ARRAY_TYPE:
+       extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+       extract_free_variables (TYPE_DOMAIN (t), wd, ADD_READ);
+       return;
+     case RECORD_TYPE:
+       extract_free_variables (TYPE_FIELDS (t), wd, ADD_READ);
+       return;
+     
+     case METHOD_TYPE:
+       extract_free_variables (TYPE_ARG_TYPES (t), wd, ADD_READ);
+       extract_free_variables (TYPE_METHOD_BASETYPE (t), wd, ADD_READ);
+       return;
+     case AGGR_INIT_EXPR:
+     case CALL_EXPR:
+       {
+       int len = 0;
+       int ii = 0;
+       if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST)
+         {
++          len = tree_to_uhwi (TREE_OPERAND (t, 0));
+           for (ii = 0; ii < len; ii++)
+             extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ);
+           extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+         }
+       break;
+       }
+     default:
+       if (is_expr)
+       {
+         int i, len;
+         /* Walk over all the sub-trees of this operand.  */
+         len = TREE_CODE_LENGTH (code);
+         /* Go through the subtrees.  We need to do this in forward order so
+            that the scope of a FOR_EXPR is handled properly.  */
+         for (i = 0; i < len; ++i)
+           extract_free_variables (TREE_OPERAND (t, i), wd, ADD_READ);
+       }
+     }
+ }
+ /* Add appropriate frames needed for a Cilk spawned function call, FNDECL. 
+    Returns the __cilkrts_stack_frame * variable.  */
+ tree
+ insert_cilk_frame (tree fndecl)
+ {
+   tree addr, body, enter, out, orig_body;
+   location_t loc = EXPR_LOCATION (fndecl);
+   if (!cfun || cfun->decl != fndecl)
+     push_cfun (DECL_STRUCT_FUNCTION (fndecl)); 
+   tree decl = cfun->cilk_frame_decl;
+   if (!decl)
+     {
+       tree *saved_tree = &DECL_SAVED_TREE (fndecl);
+       decl = make_cilk_frame (fndecl);
+       add_local_decl (cfun, decl);
+       addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, decl);
+       enter = build_call_expr (cilk_enter_fndecl, 1, addr);
+       out = create_cilk_function_exit (cfun->cilk_frame_decl, false, true);
+       /* The new body will be:
+        __cilkrts_enter_frame_1 (&sf);
+        try {
+           orig_body;
+        } 
+        finally {
+            __cilkrts_pop_frame (&sf);
+            __cilkrts_leave_frame (&sf);
+          }  */
+       body = alloc_stmt_list ();
+       orig_body = *saved_tree;
+       if (TREE_CODE (orig_body) == BIND_EXPR)
+       orig_body = BIND_EXPR_BODY (orig_body);
+  
+       append_to_statement_list (enter, &body);
+       append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, orig_body, 
+                                           out), &body);
+       if (TREE_CODE (*saved_tree) == BIND_EXPR)
+       BIND_EXPR_BODY (*saved_tree) = body;
+       else
+       *saved_tree = body;
+     }
+   return decl;
+ }
+ /* Wraps CALL, a CALL_EXPR, into a CILK_SPAWN_STMT tree and returns it.  */
+ tree
+ build_cilk_spawn (location_t loc, tree call)
+ {
+   if (!cilk_set_spawn_marker (loc, call))
+     return error_mark_node;
+   tree spawn_stmt = build1 (CILK_SPAWN_STMT, TREE_TYPE (call), call);
+   TREE_SIDE_EFFECTS (spawn_stmt) = 1;
+   return spawn_stmt;
+ }
+ /* Returns a tree of type CILK_SYNC_STMT.  */
+ tree
+ build_cilk_sync (void)
+ {
+   tree sync = build0 (CILK_SYNC_STMT, void_type_node);
+   TREE_SIDE_EFFECTS (sync) = 1;
+   return sync;
+ }
diff --cc gcc/c/c-decl.c
Simple merge
Simple merge
Simple merge
diff --cc gcc/cfgexpand.c
Simple merge
diff --cc gcc/cfgloop.c
Simple merge
diff --cc gcc/cgraph.c
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,ca178c00cd365f3e2d39924baf944154a1b160ea..9be864d5a7e7645a2e4e656bda66d1705b960c07
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,484 +1,484 @@@
 -    tree_low_cst (DECL_FIELD_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL]), 0) +
 -    tree_low_cst (DECL_FIELD_BIT_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL]), 0) /
+ /* This file is part of the Intel(R) Cilk(TM) Plus support
+    This file contains the CilkPlus Intrinsics
+    Copyright (C) 2013 Free Software Foundation, Inc.
+    Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+    Intel Corporation
+ This file is part of GCC.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tree.h"
+ #include "langhooks.h"
+ #include "expr.h"
+ #include "optabs.h"
+ #include "recog.h"
+ #include "tree-iterator.h"
+ #include "gimple.h"
+ #include "cilk.h"
+ /* This structure holds all the important fields of the internal structures,
+    internal built-in functions, and Cilk-specific data types.  Explanation of 
+    all the these fielsd are given in cilk.h.  */
+ tree cilk_trees[(int) CILK_TI_MAX];
+ /* Returns the value in structure FRAME pointed by the FIELD_NUMBER
+    (e.g. X.y).  
+    FIELD_NUMBER is an index to the structure FRAME_PTR.  For details
+    about these fields, refer to cilk_trees structure in cilk.h and
+    cilk_init_builtins function  in this file.  Returns a TREE that is the type 
+    of the field represented by FIELD_NUMBER.  If VOLATIL parameter is set
+    to true then the returning field is set as volatile.  */
+ tree
+ cilk_dot (tree frame, int field_number, bool volatil)
+ {
+   tree field = cilk_trees[field_number];
+   field = fold_build3 (COMPONENT_REF, TREE_TYPE (field), frame, field, 
+                      NULL_TREE);
+   TREE_THIS_VOLATILE (field) = volatil;
+   return field;
+ }
+ /* Returns the address of a field in FRAME_PTR, pointed by FIELD_NUMBER.  
+    (e.g. (&X)->y).   Please see cilk_dot function for explanation of the 
+    FIELD_NUMBER.  Returns a tree that is the type of the field represented 
+    by FIELD_NUMBER. If VOLATIL parameter is set to true then the returning
+    field is set as volatile.  */
+ tree
+ cilk_arrow (tree frame_ptr, int field_number, bool volatil)
+ {
+   return cilk_dot (fold_build1 (INDIRECT_REF, 
+                               TREE_TYPE (TREE_TYPE (frame_ptr)), frame_ptr), 
+                  field_number, volatil);
+ }
+ /* This function will add FIELD of type TYPE to a defined built-in 
+    structure.  *NAME is the name of the field to be added.  */
+ static tree
+ add_field (const char *name, tree type, tree fields)
+ {
+   tree t = get_identifier (name);
+   tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL, t, type);
+   TREE_CHAIN (field) = fields;
+   return field;
+ }
+ /* This function will define a built-in function of NAME, of type FNTYPE and
+    register it under the built-in function code CODE.  If PUBLISH is set then
+    the declaration is pushed into the declaration list.  CODE is the index
+    to the cilk_trees array.  *NAME is the name of the function to be added.  */
+ static tree
+ install_builtin (const char *name, tree fntype, enum built_in_function code,
+                  bool publish)
+ {
+   tree fndecl = build_fn_decl (name, fntype);
+   DECL_BUILT_IN_CLASS (fndecl) = BUILT_IN_NORMAL;
+   DECL_FUNCTION_CODE (fndecl) = code;
+   if (publish)
+     {
+       tree t = lang_hooks.decls.pushdecl (fndecl);
+       if (t)
+         fndecl = t;
+     }
+   set_builtin_decl (code, fndecl, true);
+   return fndecl;
+ }
+ /* Creates and initializes all the built-in Cilk keywords functions and three
+    structures: __cilkrts_stack_frame, __cilkrts_pedigree and __cilkrts_worker.
+    Detailed information about __cilkrts_stack_frame and
+    __cilkrts_worker structures are given in libcilkrts/include/internal/abi.h.
+    __cilkrts_pedigree is described in libcilkrts/include/cilk/common.h.  */
+ void
+ cilk_init_builtins (void)
+ {
+   /* Now build the following __cilkrts_pedigree struct:
+      struct __cilkrts_pedigree {
+         uint64_t rank;
+         struct __cilkrts_pedigree *parent;
+       }  */
+        
+   tree pedigree_type = lang_hooks.types.make_type (RECORD_TYPE);
+   tree pedigree_ptr  = build_pointer_type (pedigree_type);
+   tree field = add_field ("rank", uint64_type_node, NULL_TREE);
+   cilk_trees[CILK_TI_PEDIGREE_RANK] = field;
+   field = add_field ("parent", pedigree_ptr, field);
+   cilk_trees[CILK_TI_PEDIGREE_PARENT] = field;
+   finish_builtin_struct (pedigree_type, "__cilkrts_pedigree_GCC", field,
+                        NULL_TREE);
+   lang_hooks.types.register_builtin_type (pedigree_type,
+                                         "__cilkrts_pedigree_t");
+   cilk_pedigree_type_decl = pedigree_type; 
+   
+   /* Build the Cilk Stack Frame:
+      struct __cilkrts_stack_frame {
+        uint32_t flags;
+        uint32_t size;
+        struct __cilkrts_stack_frame *call_parent;
+        __cilkrts_worker *worker;
+        void *except_data;
+        void *ctx[4];
+        uint32_t mxcsr;
+        uint16_t fpcsr;
+        uint16_t reserved;
+        __cilkrts_pedigree pedigree;
+      };  */
+   tree frame = lang_hooks.types.make_type (RECORD_TYPE);
+   tree frame_ptr = build_pointer_type (frame);
+   tree worker_type = lang_hooks.types.make_type (RECORD_TYPE);
+   tree worker_ptr = build_pointer_type (worker_type);
+   tree s_type_node = build_int_cst (size_type_node, 4);
+   tree flags = add_field ("flags", uint32_type_node, NULL_TREE);
+   tree size = add_field ("size", uint32_type_node, flags);
+   tree parent = add_field ("call_parent", frame_ptr, size);
+   tree worker = add_field ("worker", worker_ptr, parent);
+   tree except = add_field ("except_data", frame_ptr, worker);
+   tree context = add_field ("ctx",
+                           build_array_type (ptr_type_node,
+                                             build_index_type (s_type_node)),
+                           except);
+   tree mxcsr = add_field ("mxcsr", uint32_type_node, context);
+   tree fpcsr = add_field ("fpcsr", uint16_type_node, mxcsr);
+   tree reserved = add_field ("reserved", uint16_type_node, fpcsr);
+   tree pedigree = add_field ("pedigree", pedigree_type, reserved);
+   
+   /* Now add them to a common structure whose fields are #defined to something
+      that is used at a later stage.  */
+   cilk_trees[CILK_TI_FRAME_FLAGS] = flags;
+   cilk_trees[CILK_TI_FRAME_PARENT] = parent;
+   cilk_trees[CILK_TI_FRAME_WORKER] = worker;
+   cilk_trees[CILK_TI_FRAME_EXCEPTION] = except;
+   cilk_trees[CILK_TI_FRAME_CONTEXT] = context;
+   /* We don't care about reserved, so no need to store it in cilk_trees.  */
+   cilk_trees[CILK_TI_FRAME_PEDIGREE] = pedigree;
+   TREE_ADDRESSABLE (frame) = 1;
+   finish_builtin_struct (frame, "__cilkrts_st_frame_GCC", pedigree, NULL_TREE);
+   cilk_frame_type_decl = frame;
+   lang_hooks.types.register_builtin_type (frame, "__cilkrts_frame_t");
+   cilk_frame_ptr_type_decl = build_qualified_type (frame_ptr,
+                                                  TYPE_QUAL_VOLATILE);
+   /* Now let's do the following worker struct:
+      struct __cilkrts_worker {
+        __cilkrts_stack_frame *volatile *volatile tail;
+        __cilkrts_stack_frame *volatile *volatile head;
+        __cilkrts_stack_frame *volatile *volatile exc;
+        __cilkrts_stack_frame *volatile *volatile protected_tail;
+        __cilkrts_stack_frame *volatile *ltq_limit;
+        int32_t self;
+        global_state_t *g;
+        local_state *l;
+        cilkred_map *reducer_map;
+        __cilkrts_stack_frame *current_stack_frame;
+        void *reserved;
+        __cilkrts_worker_sysdep_state *sysdep;
+        __cilkrts_pedigree pedigree;
+     }   */
+   tree fptr_volatil_type = build_qualified_type (frame_ptr, TYPE_QUAL_VOLATILE);
+   tree fptr_volatile_ptr = build_pointer_type (fptr_volatil_type);
+   tree fptr_vol_ptr_vol = build_qualified_type (fptr_volatile_ptr,
+                                               TYPE_QUAL_VOLATILE);
+   tree g = lang_hooks.types.make_type (RECORD_TYPE);
+   finish_builtin_struct (g, "__cilkrts_global_state", NULL_TREE, NULL_TREE);
+   tree l = lang_hooks.types.make_type (RECORD_TYPE);
+   finish_builtin_struct (l, "__cilkrts_local_state", NULL_TREE, NULL_TREE);
+   tree sysdep_t = lang_hooks.types.make_type (RECORD_TYPE);
+   finish_builtin_struct (sysdep_t, "__cilkrts_worker_sysdep_state", NULL_TREE,
+                        NULL_TREE);
+   
+   field = add_field ("tail", fptr_vol_ptr_vol, NULL_TREE);
+   cilk_trees[CILK_TI_WORKER_TAIL] = field;
+   field = add_field ("head", fptr_vol_ptr_vol, field);
+   field  = add_field ("exc", fptr_vol_ptr_vol, field);
+   field = add_field ("protected_tail", fptr_vol_ptr_vol, field);
+   field = add_field ("ltq_limit", fptr_volatile_ptr, field);
+   field = add_field ("self", integer_type_node, field);
+   field = add_field ("g", build_pointer_type (g), field);
+   field = add_field ("l", build_pointer_type (g), field);
+   field = add_field ("reducer_map", ptr_type_node, field);
+   field = add_field ("current_stack_frame", frame_ptr, field);
+   cilk_trees[CILK_TI_WORKER_CUR] = field;
+   field = add_field ("saved_protected_tail", fptr_volatile_ptr, field);
+   field = add_field ("sysdep", build_pointer_type (sysdep_t), field);
+   field = add_field ("pedigree", pedigree_type, field);
+   cilk_trees[CILK_TI_WORKER_PEDIGREE] = field;
+   finish_builtin_struct (worker_type, "__cilkrts_worker_GCC", field,
+                        NULL_TREE);
+   tree fptr_arglist = tree_cons (NULL_TREE, frame_ptr, void_list_node);
+   tree fptr_fun = build_function_type (void_type_node, fptr_arglist);
+   
+   /* void __cilkrts_enter_frame_1 (__cilkrts_stack_frame *);  */
+   cilk_enter_fndecl = install_builtin ("__cilkrts_enter_frame_1", fptr_fun,
+                                      BUILT_IN_CILK_ENTER_FRAME, false);
+   /* void __cilkrts_enter_frame_fast_1 (__cilkrts_stack_frame *);  */
+   cilk_enter_fast_fndecl = 
+     install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun, 
+                    BUILT_IN_CILK_ENTER_FRAME_FAST, false);
+   
+   /* void __cilkrts_pop_frame (__cilkrts_stack_frame *);  */
+   cilk_pop_fndecl = install_builtin ("__cilkrts_pop_frame", fptr_fun,
+                                    BUILT_IN_CILK_POP_FRAME, false);
+   /* void __cilkrts_leave_frame (__cilkrts_stack_frame *);  */
+   cilk_leave_fndecl = install_builtin ("__cilkrts_leave_frame", fptr_fun,
+                                      BUILT_IN_CILK_LEAVE_FRAME, false);
+   /* void __cilkrts_sync (__cilkrts_stack_frame *);  */
+   cilk_sync_fndecl = install_builtin ("__cilkrts_sync", fptr_fun,
+                                     BUILT_IN_CILK_SYNC, false);
+   /* void __cilkrts_detach (__cilkrts_stack_frame *);  */
+   cilk_detach_fndecl = install_builtin ("__cilkrts_detach", fptr_fun,
+                                       BUILT_IN_CILK_DETACH, false);
+   /* __cilkrts_rethrow (struct stack_frame *);  */
+   cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun, 
+                                        BUILT_IN_CILK_RETHROW, false);
+   /* __cilkrts_save_fp_ctrl_state (__cilkrts_stack_frame *);  */
+   cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state", 
+                                        fptr_fun, BUILT_IN_CILK_SAVE_FP,
+                                        false);
+ }
+ /* Get the appropriate frame arguments for CALL that is of type CALL_EXPR.  */
+ static tree
+ get_frame_arg (tree call)
+ {
+   tree arg, argtype;
+   gcc_assert (call_expr_nargs (call) >= 1);
+     
+   arg = CALL_EXPR_ARG (call, 0);
+   argtype = TREE_TYPE (arg);
+   gcc_assert (TREE_CODE (argtype) == POINTER_TYPE);
+   argtype = TREE_TYPE (argtype);
+   
+   gcc_assert (!lang_hooks.types_compatible_p
+             || lang_hooks.types_compatible_p (argtype, cilk_frame_type_decl));
+   /* If it is passed in as an address, then just use the value directly 
+      since the function is inlined.  */
+   if (TREE_CODE (arg) == INDIRECT_REF || TREE_CODE (arg) == ADDR_EXPR)
+     return TREE_OPERAND (arg, 0);
+   return arg;
+ }
+ /* Expands the __cilkrts_pop_frame function call stored in EXP.  */
+ void
+ expand_builtin_cilk_pop_frame (tree exp)
+ {
+   tree frame = get_frame_arg (exp);
+   tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
+   tree clear_parent = build2 (MODIFY_EXPR, void_type_node, parent,
+                             build_int_cst (TREE_TYPE (parent), 0));
+   expand_expr (clear_parent, const0_rtx, VOIDmode, EXPAND_NORMAL);
+   /* During LTO, the is_cilk_function flag gets cleared.
+      If __cilkrts_pop_frame is called, then this definitely must be a
+      cilk function.  */
+   if (cfun)
+     cfun->is_cilk_function = 1;
+ }
+ /* Expands the cilk_detach function call stored in EXP.  */
+ void
+ expand_builtin_cilk_detach (tree exp)
+ {
+   rtx insn;
+   tree fptr = get_frame_arg (exp);
+   if (fptr == NULL_TREE)
+     return;
+   tree parent = cilk_dot (fptr, CILK_TI_FRAME_PARENT, 0);
+   tree worker = cilk_dot (fptr, CILK_TI_FRAME_WORKER, 0);
+   tree tail = cilk_dot (worker, CILK_TI_WORKER_TAIL, 1);
+   rtx wreg = expand_expr (worker, NULL_RTX, Pmode, EXPAND_NORMAL);
+   if (GET_CODE (wreg) != REG)
+     wreg = copy_to_reg (wreg);
+   rtx preg = expand_expr (parent, NULL_RTX, Pmode, EXPAND_NORMAL);
+   /* TMP <- WORKER.TAIL
+     *TMP <- PARENT
+      TMP <- TMP + 1
+      WORKER.TAIL <- TMP   */
+   HOST_WIDE_INT worker_tail_offset =
++    tree_to_shwi (DECL_FIELD_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL])) +
++    tree_to_shwi (DECL_FIELD_BIT_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL])) /
+     BITS_PER_UNIT;
+   rtx tmem0 = gen_rtx_MEM (Pmode,
+                          plus_constant (Pmode, wreg, worker_tail_offset));
+   set_mem_attributes (tmem0, tail, 0);
+   MEM_NOTRAP_P (tmem0) = 1;
+   gcc_assert (MEM_VOLATILE_P (tmem0));
+   rtx treg = copy_to_mode_reg (Pmode, tmem0);
+   rtx tmem1 = gen_rtx_MEM (Pmode, treg);
+   set_mem_attributes (tmem1, TREE_TYPE (TREE_TYPE (tail)), 0);
+   MEM_NOTRAP_P (tmem1) = 1;
+   emit_move_insn (tmem1, preg);
+   emit_move_insn (treg, plus_constant (Pmode, treg, GET_MODE_SIZE (Pmode)));
+   /* There is a release barrier (st8.rel, membar #StoreStore,
+      sfence, lwsync, etc.) between the two stores.  On x86
+      normal volatile stores have proper semantics; the sfence
+      would only be needed for nontemporal stores (which we
+      could generate using the storent optab, for no benefit
+      in this case).
+      The predicate may return false even for a REG if this is
+      the limited release operation that only stores 0.  */
+   enum insn_code icode = direct_optab_handler (sync_lock_release_optab, Pmode); 
+   if (icode != CODE_FOR_nothing
+       && insn_data[icode].operand[1].predicate (treg, Pmode)
+       && (insn = GEN_FCN (icode) (tmem0, treg)) != NULL_RTX)
+     emit_insn (insn);
+   else
+     emit_move_insn (tmem0, treg);
+   /* The memory barrier inserted above should not prevent
+      the load of flags from being moved before the stores,
+      but in practice it does because it is implemented with
+      unspec_volatile.  In-order RISC machines should
+      explicitly load flags earlier.  */
+   tree flags = cilk_dot (fptr, CILK_TI_FRAME_FLAGS, 0);
+   expand_expr (build2 (MODIFY_EXPR, void_type_node, flags,
+                      build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags,
+                              build_int_cst (TREE_TYPE (flags),
+                                             CILK_FRAME_DETACHED))),
+              const0_rtx, VOIDmode, EXPAND_NORMAL);
+ }
+ /* Returns a setjmp CALL_EXPR with FRAME->context as its parameter.  */
+ tree
+ cilk_call_setjmp (tree frame)
+ {
+   tree c = cilk_dot (frame, CILK_TI_FRAME_CONTEXT, false);
+   c = build1 (ADDR_EXPR, build_pointer_type (ptr_type_node), c);
+   return build_call_expr (builtin_decl_implicit (BUILT_IN_SETJMP), 1, c);
+ }
+ /* This function will expand the _Cilk_sync keyword.  */
+ static tree
+ expand_cilk_sync (void)
+ {
+   tree frame = cfun->cilk_frame_decl;
+   /* Cilk_sync is converted to the following code:
+      sf.pedigree = sf.worker->pedigree;
+      if (frame.flags & CILK_FRAME_UNSYNCHED)
+      {
+         __cilkrts_save_fp_state (&sf);
+         if (!builtin_setjmp (sf.ctx) 
+           __cilkrts_sync (&sf); 
+       else 
+          if (sf.flags & CILK_FRAME_EXCEPTING) 
+            __cilkrts_rethrow (&sf); 
+       }
+       sf.worker->pedigree.rank = sf.worker->pedigree.rank + 1;  */
+   tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
+   
+   tree unsynched = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
+                               build_int_cst (TREE_TYPE (flags),
+                                              CILK_FRAME_UNSYNCHED));
+   unsynched = fold_build2 (NE_EXPR, TREE_TYPE (unsynched), unsynched,
+                          build_int_cst (TREE_TYPE (unsynched), 0));
+   tree frame_addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
+   /* Check if exception (0x10) bit is set in the sf->flags.  */
+   tree except_flag = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
+                                 build_int_cst (TREE_TYPE (flags),
+                                                CILK_FRAME_EXCEPTING));
+   except_flag = fold_build2 (NE_EXPR, TREE_TYPE (except_flag), except_flag,
+                            build_int_cst (TREE_TYPE (except_flag), 0));
+   /* If the exception flag is set then call the __cilkrts_rethrow (&sf).  */
+   tree except_cond = fold_build3 (COND_EXPR, void_type_node, except_flag,
+                                 build_call_expr (cilk_rethrow_fndecl, 1,
+                                                  frame_addr),
+                                 build_empty_stmt (EXPR_LOCATION (unsynched)));
+   
+   tree sync_expr = build_call_expr (cilk_sync_fndecl, 1, frame_addr);
+   tree setjmp_expr = cilk_call_setjmp (frame);
+   setjmp_expr = fold_build2 (EQ_EXPR, TREE_TYPE (setjmp_expr), setjmp_expr,
+                            build_int_cst (TREE_TYPE (setjmp_expr), 0));
+   
+   setjmp_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_expr,
+                            sync_expr, except_cond);
+   tree sync_list = alloc_stmt_list ();
+   append_to_statement_list (build_call_expr (cilk_save_fp_fndecl, 1,
+                                            frame_addr), &sync_list);
+   append_to_statement_list (setjmp_expr, &sync_list);
+   tree sync = fold_build3 (COND_EXPR, void_type_node, unsynched, sync_list,
+                          build_empty_stmt (EXPR_LOCATION (unsynched)));
+   tree parent_pedigree = cilk_dot (frame, CILK_TI_FRAME_PEDIGREE, false);
+   tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, false);
+   tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, false);
+   tree assign_pedigree = fold_build2 (MODIFY_EXPR, void_type_node,
+                                     parent_pedigree, worker_pedigree);
+   tree w_ped_rank = cilk_dot (unshare_expr (worker_pedigree), 
+                             CILK_TI_PEDIGREE_RANK, false);
+   tree incr_ped_rank = fold_build2 (PLUS_EXPR, TREE_TYPE (w_ped_rank),
+                                   w_ped_rank,
+                                   build_one_cst (TREE_TYPE (w_ped_rank)));
+   incr_ped_rank = fold_build2 (MODIFY_EXPR, void_type_node, w_ped_rank,
+                              incr_ped_rank);
+   tree ret_sync_exp = alloc_stmt_list ();
+   append_to_statement_list (assign_pedigree, &ret_sync_exp);
+   append_to_statement_list (sync, &ret_sync_exp);
+   append_to_statement_list (incr_ped_rank, &ret_sync_exp);
+   return ret_sync_exp;
+ }
+ /* Gimplifies the cilk_sync expression passed in *EXPR_P.  Returns GS_ALL_DONE 
+    when finished.  */
+ void
+ gimplify_cilk_sync (tree *expr_p, gimple_seq *pre_p)
+ {
+   tree sync_expr = expand_cilk_sync ();
+   *expr_p = NULL_TREE;
+   gimplify_and_add (sync_expr, pre_p);
+ }
Simple merge
Simple merge
index 6a2750994f5f4ea451df2388a6219e35ab724d63,e7e1c2f138bd1b57a23521027b62de18cf87a960..f0def13ae8f7c8489eae494c273cea6ab691f492
@@@ -12240,8 -12226,8 +12226,8 @@@ avr_fold_builtin (tree fndecl, int n_ar
              break;
            }
  
-         wide_int map = wide_int::from_tree (arg[0]);
-         tmap = wide_int_to_tree (map_type, map);
 -        tmap = double_int_to_tree (map_type, tree_to_double_int (arg[0]));
++        tmap = wide_int_to_tree (map_type, widest_int (arg[0]));
+         map = TREE_INT_CST_LOW (tmap);
  
          if (TREE_CODE (tval) != INTEGER_CST
              && 0 == avr_map_metric (map, MAP_MASK_PREIMAGE_F))
  
          /* Use map o G^-1 instead of original map to undo the effect of G.  */
  
-         tmap = wide_int_to_tree (map_type, best_g.map);
 -        tmap = double_int_to_tree (map_type,
 -                                 double_int::from_uhwi (best_g.map));
++        tmap = wide_int_to_tree (map_type,
++                               widest_int (best_g.map));
  
          return build_call_expr (fndecl, 3, tmap, tbits, tval);
        } /* AVR_BUILTIN_INSERT_BITS */
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/coverage.c
Simple merge
diff --cc gcc/cp/call.c
Simple merge
diff --cc gcc/cp/class.c
Simple merge
Simple merge
diff --cc gcc/cp/decl.c
Simple merge
diff --cc gcc/cp/error.c
Simple merge
diff --cc gcc/cp/init.c
Simple merge
diff --cc gcc/cp/method.c
Simple merge
diff --cc gcc/cp/parser.c
index 383ea46b7b5e506b04fd2832f4c873bba9cbfd8d,3df746a3683fbe799d9c54b950eef874eb3c008b..06d779698f4d5fc8281dc47cbff088d4ae7eb680
@@@ -3793,13 -3793,15 +3793,15 @@@ make_string_pack (tree value
    tree charvec;
    tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
    const char *str = TREE_STRING_POINTER (value);
-   int i, len = TREE_STRING_LENGTH (value) - 1;
 -  int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value))));
++  int sz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value))));
+   int len = TREE_STRING_LENGTH (value) / sz - 1;
    tree argvec = make_tree_vec (2);
  
-   tree string_char_type_node = TREE_TYPE (TREE_TYPE (value));
+   tree str_char_type_node = TREE_TYPE (TREE_TYPE (value));
+   str_char_type_node = TYPE_MAIN_VARIANT (str_char_type_node);
  
    /* First template parm is character type.  */
-   TREE_VEC_ELT (argvec, 0) = string_char_type_node;
+   TREE_VEC_ELT (argvec, 0) = str_char_type_node;
  
    /* Fill in CHARVEC with all of the parameters.  */
    charvec = make_tree_vec (len);
Simple merge
diff --cc gcc/cp/tree.c
Simple merge
Simple merge
Simple merge
diff --cc gcc/dbxout.c
Simple merge
Simple merge
Simple merge
diff --cc gcc/doc/tm.texi
Simple merge
Simple merge
diff --cc gcc/dwarf2out.c
Simple merge
diff --cc gcc/except.c
Simple merge
diff --cc gcc/expmed.c
Simple merge
diff --cc gcc/expr.c
index 60d9de625823c335b5380651d560f843db843b33,551a66059b9a034a922063df90c1b48e6241de57..c751004c68e4d39dcbc2a665f02e0f4a90a895e2
@@@ -9620,13 -9583,14 +9568,13 @@@ expand_expr_real_1 (tree exp, rtx targe
          }
        align = get_object_alignment (exp);
        op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
-       op0 = memory_address_addr_space (address_mode, op0, as);
+       op0 = memory_address_addr_space (mode, op0, as);
        if (!integer_zerop (TREE_OPERAND (exp, 1)))
          {
 -          rtx off
 -            = immed_double_int_const (mem_ref_offset (exp), address_mode);
 +          rtx off = immed_wide_int_const (mem_ref_offset (exp), address_mode);
            op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
+           op0 = memory_address_addr_space (mode, op0, as);
          }
-       op0 = memory_address_addr_space (mode, op0, as);
        temp = gen_rtx_MEM (mode, op0);
        set_mem_attributes (temp, exp, 0);
        set_mem_addr_space (temp, as);
diff --cc gcc/expr.h
index f0bbb0ed5d6af269d10f10fcbc892767ec9254d5,56f504ac1552b1308a78137bfa94af96f2fe22ee..ca93058e5e18100bd248ed598ec2e9de2af9e39a
@@@ -26,9 -26,9 +26,9 @@@ along with GCC; see the file COPYING3
  #include "rtl.h"
  /* For optimize_size */
  #include "flags.h"
 -/* For host_integerp, tree_low_cst, fold_convert, size_binop, ssize_int,
 +/* For tree_fits_uhwi_p, tree_to_uhwi, fold_convert, size_binop, ssize_int,
     TREE_CODE, TYPE_SIZE, int_size_in_bytes,    */
- #include "tree.h"
+ #include "tree-core.h"
  /* For GET_MODE_BITSIZE, word_mode */
  #include "machmode.h"
  
diff --cc gcc/final.c
Simple merge
Simple merge
index 937fda529b8a60773e5f29e7a37fb9fb2356415e,e905b3a67dcb503894826893343ed3f7be91719b..da8c7bf11658c9e5acc8e2b175a2348d8969bb11
@@@ -31,9 -31,8 +31,9 @@@ along with GCC; see the file COPYING3
  #include "trans-const.h"
  #include "trans-types.h"
  #include "target-memory.h"
 +#include "wide-int.h"
  
- /* --------------------------------------------------------------- */ 
+ /* --------------------------------------------------------------- */
  /* Calculate the size of an expression.  */
  
  
Simple merge
diff --cc gcc/function.c
Simple merge
diff --cc gcc/gcse.c
Simple merge
diff --cc gcc/genemit.c
Simple merge
Simple merge
Simple merge
diff --cc gcc/gengtype.c
index e2d9dd4f9476fc214bf07dd3b3defafe22e15fa9,f35952e5a55583bc8587dc84804ea48f172f6458..c82536df206bace8a1fc3e9578880b3b10d1617a
@@@ -1732,11 -1766,15 +1765,15 @@@ open_base_files (void
      static const char *const ifiles[] = {
        "config.h", "system.h", "coretypes.h", "tm.h",
        "hashtab.h", "splay-tree.h", "obstack.h", "bitmap.h", "input.h",
 -      "tree.h", "rtl.h", "function.h", "insn-config.h", "expr.h",
 +      "tree.h", "rtl.h", "wide-int.h", "function.h", "insn-config.h", "expr.h",
        "hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h",
        "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
+       "gimple.h", "gimple-ssa.h", "tree-cfg.h", "tree-phinodes.h",
+       "ssa-iterators.h", "tree-ssanames.h", "tree-ssa-loop.h",
+       "tree-ssa-loop-ivopts.h", "tree-ssa-loop-manip.h",
+       "tree-ssa-loop-niter.h", "tree-into-ssa.h", "tree-dfa.h", 
        "tree-ssa.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
-       "except.h", "output.h", "gimple.h", "cfgloop.h",
+       "except.h", "output.h",  "cfgloop.h",
        "target.h", "ipa-prop.h", "lto-streamer.h", "target-globals.h",
        "ipa-inline.h", "dwarf2out.h", NULL
      };
diff --cc gcc/genmodes.c
Simple merge
Simple merge
index a45dd535d9523cb642263335b85ad90939516840,6842213199af8f1edcdce0176587aaee08b6f130..c95b9c463571d41531354fcc5a1de07603a5ee9d
@@@ -1728,7 -1737,7 +1737,7 @@@ dump_ssaname_info (pretty_printer *buff
    if (!POINTER_TYPE_P (TREE_TYPE (node))
        && SSA_NAME_RANGE_INFO (node))
      {
-       widest_int min, max;
 -      double_int min, max, nonzero_bits;
++      widest_int min, max, nonzero_bits;
        value_range_type range_type = get_range_info (node, &min, &max);
  
        if (range_type == VR_VARYING)
        {
          pp_printf (buffer, "# RANGE ");
          pp_printf (buffer, "%s[", range_type == VR_RANGE ? "" : "~");
 -        pp_double_int (buffer, min, TYPE_UNSIGNED (TREE_TYPE (node)));
 +        pp_wide_int (buffer, min, TYPE_SIGN (TREE_TYPE (node)));
          pp_printf (buffer, ", ");
 -        pp_double_int (buffer, max, TYPE_UNSIGNED (TREE_TYPE (node)));
 +        pp_wide_int (buffer, max, TYPE_SIGN (TREE_TYPE (node)));
          pp_printf (buffer, "]");
-         newline_and_indent (buffer, spc);
        }
 -      if (nonzero_bits != double_int_minus_one
+       nonzero_bits = get_nonzero_bits (node);
 -            != double_int::mask (TYPE_PRECISION (TREE_TYPE (node)))))
++      if (nonzero_bits != -1
+         && (nonzero_bits
 -        sprintf (pp_buffer (buffer)->digit_buffer,
 -                 HOST_WIDE_INT_PRINT_DOUBLE_HEX,
 -                 (unsigned HOST_WIDE_INT) nonzero_bits.high,
 -                 nonzero_bits.low);
 -        pp_string (buffer, pp_buffer (buffer)->digit_buffer);
++            != wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (node)), false)))
+       {
+         pp_string (buffer, " NONZERO ");
++        pp_wide_int (buffer, nonzero_bits, UNSIGNED);
+       }
+       newline_and_indent (buffer, spc);
      }
  }
  
Simple merge
diff --cc gcc/gimple.c
Simple merge
diff --cc gcc/gimplify.c
index 21861d244eafcf904abfb38a54a124f9c61dfd3a,0723027c392f25f579c37d5dcde276d6fcd53ea4..21dc7cad156918de572526e58f8cd98081247892
@@@ -3068,6 -3088,17 +3084,17 @@@ gimple_boolify (tree expr
        TREE_TYPE (expr) = boolean_type_node;
        return expr;
  
 -      if ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1))
+     case ANNOTATE_EXPR:
++      if ((enum annot_expr_kind) tree_to_uhwi (TREE_OPERAND (expr, 1))
+         == annot_expr_ivdep_kind)
+       {
+         TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
+         if (TREE_CODE (type) != BOOLEAN_TYPE)
+           TREE_TYPE (expr) = boolean_type_node;
+         return expr;
+       }
+       /* FALLTHRU */
      default:
        if (COMPARISON_CLASS_P (expr))
        {
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/ipa-cp.c
Simple merge
Simple merge
diff --cc gcc/ipa-prop.c
Simple merge
diff --cc gcc/ipa-utils.h
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/lto/lto.c
Simple merge
Simple merge
diff --cc gcc/omp-low.c
Simple merge
diff --cc gcc/optabs.c
Simple merge
diff --cc gcc/predict.c
Simple merge
index e38f59abcb5f6ff8c943cae31756de33fbd04e42,e5d6664c22926ce4f3edf37f3ae076d37526fc92..d6cf945d385373ff016c7fd32b9720349026ba32
@@@ -28,10 -28,10 +28,11 @@@ along with GCC; see the file COPYING3
  #include "tree-iterator.h"
  #include "diagnostic.h"
  #include "gimple-pretty-print.h" /* FIXME */
- #include "tree-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
  #include "tree-dump.h"
  #include "dumpfile.h"
 +#include "wide-int-print.h"
  
  /* Define the hash table of nodes already seen.
     Such nodes are not repeated; brief cross-references are used.  */
diff --cc gcc/recog.c
Simple merge
Simple merge
diff --cc gcc/targhooks.c
Simple merge
diff --cc gcc/trans-mem.c
Simple merge
Simple merge
diff --cc gcc/tree-cfg.c
index 94be3610c9102e34613e917e1ca3ae55837a5533,d646693903259340de65f4f5beb20a4f59df8e02..6c551f4fe96237e4008dc19bfba15dc13e254fff
@@@ -241,6 -250,72 +252,72 @@@ build_gimple_cfg (gimple_seq seq
    discriminator_per_locus.dispose ();
  }
  
 -        if ((annot_expr_kind) tree_low_cst (gimple_call_arg (stmt, 1), 0)
+ /* Search for ANNOTATE call with annot_expr_ivdep_kind; if found, remove
+    it and set loop->safelen to INT_MAX.  We assume that the annotation
+    comes immediately before the condition.  */
+ static void
+ replace_loop_annotate ()
+ {
+   struct loop *loop;
+   loop_iterator li;
+   basic_block bb;
+   gimple_stmt_iterator gsi;
+   gimple stmt;
+   FOR_EACH_LOOP (li, loop, 0)
+     {
+       gsi = gsi_last_bb (loop->header);
+       stmt = gsi_stmt (gsi);
+       if (stmt && gimple_code (stmt) == GIMPLE_COND)
+       {
+         gsi_prev_nondebug (&gsi);
+         if (gsi_end_p (gsi))
+           continue;
+         stmt = gsi_stmt (gsi);
+         if (gimple_code (stmt) != GIMPLE_CALL)
+               continue;
+         if (!gimple_call_internal_p (stmt)
+                 || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+           continue;
 -      if ((annot_expr_kind) tree_low_cst (gimple_call_arg (stmt, 1), 0)
++        if ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1))
+             != annot_expr_ivdep_kind)
+           continue;
+         stmt = gimple_build_assign (gimple_call_lhs (stmt),
+                                     gimple_call_arg (stmt, 0));
+         gsi_replace (&gsi, stmt, true);
+         loop->safelen = INT_MAX;
+       }
+     }
+   /* Remove IFN_ANNOTATE. Safeguard for the case loop->latch == NULL.  */
+   FOR_EACH_BB (bb)
+     {
+       gsi = gsi_last_bb (bb);
+       stmt = gsi_stmt (gsi);
+       if (stmt && gimple_code (stmt) == GIMPLE_COND)
+       gsi_prev_nondebug (&gsi);
+       if (gsi_end_p (gsi))
+       continue;
+       stmt = gsi_stmt (gsi);
+       if (gimple_code (stmt) != GIMPLE_CALL)
+       continue;
+       if (!gimple_call_internal_p (stmt)
+         || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+       continue;
++      if ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1))
+         != annot_expr_ivdep_kind)
+       continue;
+       warning_at (gimple_location (stmt), 0, "ignoring %<GCC ivdep%> "
+                 "annotation");
+       stmt = gimple_build_assign (gimple_call_lhs (stmt),
+                                 gimple_call_arg (stmt, 0));
+       gsi_replace (&gsi, stmt, true);
+     }
+ }
  static unsigned int
  execute_build_cfg (void)
  {
Simple merge
diff --cc gcc/tree-core.h
Simple merge
Simple merge
diff --cc gcc/tree-dfa.c
Simple merge
Simple merge
Simple merge
Simple merge
index c88d0731acf0efcb8c33dd7274cdd9da5f16ecac,fe756339f6d420110222352b7b51092238f2f505..1d831ee24abf7ecc7d4896a57acf6362b84651cc
@@@ -2108,6 -2096,18 +2110,18 @@@ dump_generic_node (pretty_printer *buff
        pp_string (buffer, " predictor.");
        break;
  
 -      switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (node, 1)))
+     case ANNOTATE_EXPR:
+       pp_string (buffer, "ANNOTATE_EXPR <");
++      switch ((enum annot_expr_kind) tree_to_shwi (TREE_OPERAND (node, 1)))
+       {
+       case annot_expr_ivdep_kind:
+         pp_string (buffer, "ivdep, ");
+         break;
+       }
+       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+       pp_greater (buffer);
+       break;
      case RETURN_EXPR:
        pp_string (buffer, "return");
        op0 = TREE_OPERAND (node, 0);
diff --cc gcc/tree-sra.c
Simple merge
Simple merge
index 5e80e66479c0ec05351c69c26d57100036da4348,efc08c20991973d7ffe0e49de9435cb398664c33..1a58ce722ed4593009d82789de169e10a7058528
@@@ -565,8 -566,24 +566,24 @@@ ao_ref_alias_set (ao_ref *ref
  void
  ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size)
  {
-   HOST_WIDE_INT t1, t2;
+   HOST_WIDE_INT t1, t2, extra_offset = 0;
    ref->ref = NULL_TREE;
 -             && host_integerp (gimple_assign_rhs2 (stmt), 0)
+   if (TREE_CODE (ptr) == SSA_NAME)
+     {
+       gimple stmt = SSA_NAME_DEF_STMT (ptr);
+       if (gimple_assign_single_p (stmt)
+         && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
+       ptr = gimple_assign_rhs1 (stmt);
+       else if (is_gimple_assign (stmt)
+              && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
++             && tree_fits_shwi_p (gimple_assign_rhs2 (stmt))
+              && (t1 = int_cst_value (gimple_assign_rhs2 (stmt))) >= 0)
+       {
+         ptr = gimple_assign_rhs1 (stmt);
+         extra_offset = BITS_PER_UNIT * t1;
+       }
+     }
    if (TREE_CODE (ptr) == ADDR_EXPR)
      ref->base = get_ref_base_and_extent (TREE_OPERAND (ptr, 0),
                                         &ref->offset, &t1, &t2);
                          ptr, null_pointer_node);
        ref->offset = 0;
      }
+   ref->offset += extra_offset;
    if (size
 -      && host_integerp (size, 0)
 -      && TREE_INT_CST_LOW (size) * BITS_PER_UNIT / BITS_PER_UNIT
 -       == TREE_INT_CST_LOW (size))
 -    ref->max_size = ref->size = TREE_INT_CST_LOW (size) * BITS_PER_UNIT;
 +      && tree_fits_shwi_p (size)
-       && tree_to_shwi (size) * 8 / 8 == tree_to_shwi (size))
-     ref->max_size = ref->size = tree_to_shwi (size) * 8;
++      && tree_to_shwi (size) * BITS_PER_UNIT / BITS_PER_UNIT == tree_to_shwi (size))
++    ref->max_size = ref->size = tree_to_shwi (size) * BITS_PER_UNIT;
    else
      ref->max_size = ref->size = -1;
    ref->ref_alias_set = 0;
index 202703b20529e8cb45fa68f32837d4bb804dc170,5b6c0dbea28adfb1cbdf1a7758ffb2fbfec7b960..1c86bf93e9a719af0b8e92494cc89f5c23dc08bb
@@@ -266,7 -259,20 +271,20 @@@ get_default_value (tree var
        else
        {
          val.lattice_val = VARYING;
 -        val.mask = double_int_minus_one;
 +        val.mask = -1;
+         if (flag_tree_bit_ccp)
+           {
 -            double_int nonzero_bits = get_nonzero_bits (var);
 -            double_int mask
 -              = double_int::mask (TYPE_PRECISION (TREE_TYPE (var)));
 -            if (nonzero_bits != double_int_minus_one && nonzero_bits != mask)
++            widest_int nonzero_bits = get_nonzero_bits (var);
++            widest_int mask
++              = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (var)), false);
++            if (nonzero_bits != -1 && nonzero_bits != mask)
+               {
+                 val.lattice_val = CONSTANT;
+                 val.value = build_zero_cst (TREE_TYPE (var));
+                 /* CCP wants the bits above precision set.  */
+                 val.mask = nonzero_bits | ~mask;
+               }
+           }
        }
      }
    else if (is_gimple_assign (stmt))
@@@ -848,13 -862,24 +871,24 @@@ ccp_finalize (void
          || TREE_CODE (val->value) != INTEGER_CST)
        continue;
  
-       /* Trailing constant bits specify the alignment, trailing value
-        bits the misalignment.  */
-       tem = val->mask.to_uhwi ();
-       align = (tem & -tem);
-       if (align > 1)
-       set_ptr_info_alignment (get_ptr_info (name), align,
-                               tree_to_hwi (val->value) & (align - 1));
+       if (POINTER_TYPE_P (TREE_TYPE (name)))
+       {
+         /* Trailing mask bits specify the alignment, trailing value
+            bits the misalignment.  */
 -        tem = val->mask.low;
++        tem = val->mask.to_uhwi ();
+         align = (tem & -tem);
+         if (align > 1)
+           set_ptr_info_alignment (get_ptr_info (name), align,
 -                                  (TREE_INT_CST_LOW (val->value)
++                                  (tree_to_hwi (val->value)
+                                    & (align - 1)));
+       }
+       else
+       {
 -        double_int nonzero_bits = val->mask;
 -        nonzero_bits = nonzero_bits | tree_to_double_int (val->value);
++        widest_int nonzero_bits = val->mask;
++        nonzero_bits = nonzero_bits | wi::to_widest (val->value);
+         nonzero_bits &= get_nonzero_bits (name);
+         set_nonzero_bits (name, nonzero_bits);
+       }
      }
  
    /* Perform substitutions based on the known constant values.  */
@@@ -1712,6 -1700,39 +1746,39 @@@ evaluate_stmt (gimple stmt
        is_constant = (val.lattice_val == CONSTANT);
      }
  
 -      double_int nonzero_bits = get_nonzero_bits (lhs);
 -      double_int mask = double_int::mask (TYPE_PRECISION (TREE_TYPE (lhs)));
 -      if (nonzero_bits != double_int_minus_one && nonzero_bits != mask)
+   if (flag_tree_bit_ccp
+       && ((is_constant && TREE_CODE (val.value) == INTEGER_CST)
+         || (!is_constant && likelyvalue != UNDEFINED))
+       && gimple_get_lhs (stmt)
+       && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME)
+     {
+       tree lhs = gimple_get_lhs (stmt);
 -            double_int valv = tree_to_double_int (val.value);
 -            if (!(valv & ~nonzero_bits & mask).is_zero ())
 -              val.value = double_int_to_tree (TREE_TYPE (lhs),
 -                                              valv & nonzero_bits);
 -            if (nonzero_bits.is_zero ())
 -              val.mask = double_int_zero;
++      widest_int nonzero_bits = get_nonzero_bits (lhs);
++      widest_int mask = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (lhs)), false);
++      if (nonzero_bits != -1 && nonzero_bits != mask)
+       {
+         if (!is_constant)
+           {
+             val.lattice_val = CONSTANT;
+             val.value = build_zero_cst (TREE_TYPE (lhs));
+             /* CCP wants the bits above precision set.  */
+             val.mask = nonzero_bits | ~mask;
+             is_constant = true;
+           }
+         else
+           {
++            widest_int valv = wi::to_widest (val.value);
++            if ((valv & ~nonzero_bits & mask) != 0)
++              val.value = wide_int_to_tree (TREE_TYPE (lhs),
++                                            valv & nonzero_bits);
++            if (nonzero_bits == 0)
++              val.mask = 0;
+             else
+               val.mask = val.mask & (nonzero_bits | ~mask);
+           }
+       }
+     }
    if (!is_constant)
      {
        /* The statement produced a nonconstant value.  If the statement
Simple merge
Simple merge
Simple merge
index 6846fcf6115b6f8bf26a1a2308bfb6258c430875,0210dbbad3df77299bc5ad12522c798038243ad6..9e6a9920bad4968e694d7c6e4346d52ccd4174a7
@@@ -2107,19 -2119,32 +2119,32 @@@ strip_offset_1 (tree expr, bool inside_
        break;
  
      case COMPONENT_REF:
-       if (!inside_addr)
-       return orig_expr;
-       tmp = component_ref_field_offset (expr);
-       if (top_compref
-         && cst_fits_shwi_p (tmp))
-       {
-         /* Strip the component reference completely.  */
-         op0 = TREE_OPERAND (expr, 0);
-         op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
-         *offset = off0 + int_cst_value (tmp);
-         return op0;
-       }
+       {
+       tree field;
+       if (!inside_addr)
+         return orig_expr;
+       tmp = component_ref_field_offset (expr);
+       field = TREE_OPERAND (expr, 1);
+       if (top_compref
 -          && cst_and_fits_in_hwi (tmp)
 -          && cst_and_fits_in_hwi (DECL_FIELD_BIT_OFFSET (field)))
++          && cst_fits_shwi_p (tmp)
++          && cst_fits_shwi_p (DECL_FIELD_BIT_OFFSET (field)))
+         {
+           HOST_WIDE_INT boffset, abs_off;
+           /* Strip the component reference completely.  */
+           op0 = TREE_OPERAND (expr, 0);
+           op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
+           boffset = int_cst_value (DECL_FIELD_BIT_OFFSET (field));
+           abs_off = abs_hwi (boffset) / BITS_PER_UNIT;
+           if (boffset < 0)
+             abs_off = -abs_off;
+           *offset = off0 + int_cst_value (tmp) + abs_off;
+           return op0;
+         }
+       }
        break;
  
      case ADDR_EXPR:
Simple merge
Simple merge
index 3f6a6bcc5faa750412b1f7c18a2e12b52d7b2b5c,82799ff6adcb1f4b9def416535142811c0fc01f7..0eb8b742f9266dfc3c542b7afad6433961bd294c
@@@ -20,11 -20,6 +20,8 @@@ along with GCC; see the file COPYING3
  #ifndef GCC_TREE_SSA_LOOP_H
  #define GCC_TREE_SSA_LOOP_H
  
- #include "tree-ssa-loop-ivopts.h"
- #include "tree-ssa-loop-manip.h"
- #include "tree-ssa-loop-niter.h"
 +#include "wide-int.h"
 +
  /* Affine iv.  */
  
  typedef struct affine_iv_d
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/tree-ssa.c
Simple merge
index b1ef37d687918a6626ba2e25a2ecddf675f9861f,763589125695ce9f4402e58aa41162e9c3d08f97..2c177eeaec8affbffde0db9a5be13d2a12b0170a
@@@ -183,11 -189,30 +189,29 @@@ set_range_info (tree name, widest_int m
      {
        ri = ggc_alloc_cleared_range_info_def ();
        SSA_NAME_RANGE_INFO (name) = ri;
 -      ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
++      ri->nonzero_bits = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)),
++                                              false);
      }
  
    /* Set the values.  */
    ri->min = min;
    ri->max = max;
 -  if (min.cmp (max, TYPE_UNSIGNED (TREE_TYPE (name))) != 1)
+   /* If it is a range, try to improve nonzero_bits from the min/max.  */
 -      double_int xorv;
++  if (wi::cmp (min, max, TYPE_SIGN (TREE_TYPE (name))) != 1)
+     {
+       int prec = TYPE_PRECISION (TREE_TYPE (name));
 -      min = min.zext (prec);
 -      max = max.zext (prec);
++      widest_int xorv;
 -      if (xorv.high)
 -      xorv = double_int::mask (2 * HOST_BITS_PER_WIDE_INT
 -                               - clz_hwi (xorv.high));
 -      else if (xorv.low)
 -      xorv = double_int::mask (HOST_BITS_PER_WIDE_INT
 -                               - clz_hwi (xorv.low));
++      min = wi::zext (min, prec);
++      max = wi::zext (max, prec);
+       xorv = min ^ max;
++      if (xorv != 0)
++      xorv = wi::mask <widest_int> (MAX_BITSIZE_MODE_ANY_INT
++                                    - wi::clz (xorv),
++                                    false);
+       ri->nonzero_bits = ri->nonzero_bits & (min | xorv);
+     }
  }
  
  
     is used to determine if MIN and MAX are valid values.  */
  
  enum value_range_type
- get_range_info (tree name, widest_int *min, widest_int *max)
 -get_range_info (const_tree name, double_int *min, double_int *max)
++get_range_info (const_tree name, widest_int *min, widest_int *max)
  {
    enum value_range_type range_type;
    gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
    return range_type;
  }
  
 -set_nonzero_bits (tree name, double_int mask)
+ /* Change non-zero bits bitmask of NAME.  */
+ void
 -                  tree_to_double_int (TYPE_MIN_VALUE (TREE_TYPE (name))),
 -                  tree_to_double_int (TYPE_MAX_VALUE (TREE_TYPE (name))));
++set_nonzero_bits (tree name, widest_int mask)
+ {
+   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+   if (SSA_NAME_RANGE_INFO (name) == NULL)
+     set_range_info (name,
 -    = mask & double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
++                  wi::to_widest (TYPE_MIN_VALUE (TREE_TYPE (name))),
++                  wi::to_widest (TYPE_MAX_VALUE (TREE_TYPE (name))));
+   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+   ri->nonzero_bits
 -/* Return a double_int with potentially non-zero bits in SSA_NAME
 -   NAME, or double_int_minus_one if unknown.  */
++    = mask & wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)),
++                                  false);
+ }
 -double_int
++/* Return a widest_int with potentially non-zero bits in SSA_NAME
++   NAME, or -1 if unknown.  */
 -        double_int al = double_int::from_uhwi (pi->align - 1);
 -        return ((double_int::mask (TYPE_PRECISION (TREE_TYPE (name))) & ~al)
 -                | double_int::from_uhwi (pi->misalign));
++widest_int
+ get_nonzero_bits (const_tree name)
+ {
+   if (POINTER_TYPE_P (TREE_TYPE (name)))
+     {
+       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
+       if (pi && pi->align)
+       {
 -      return double_int_minus_one;
++        widest_int al = pi->align - 1;
++        return ((wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)),
++                                        false) & ~al)
++                | pi->misalign);
+       }
 -    return double_int_minus_one;
++      return -1;
+     }
+   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+   if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
+             > 2 * HOST_BITS_PER_WIDE_INT))
++    return -1;
+   return ri->nonzero_bits;
+ }
  /* We no longer need the SSA_NAME expression VAR, release it so that
     it may be reused.
  
index 2c92d5772d74af33985e3b79f86f3468f131d377,d0a654252111eae6776d5487d3925454a74fecb1..cafcd7c482af0b904616f877c4b6fc18fa63c64d
@@@ -49,9 -49,11 +49,11 @@@ struct GTY(()) ptr_info_de
  
  struct GTY (()) range_info_def {
    /* Minimum for value range.  */
 -  double_int min;
 +  widest_int min;
    /* Maximum for value range.  */
 -  double_int max;
 +  widest_int max;
+   /* Non-zero bits - bits not set are guaranteed to be always zero.  */
 -  double_int nonzero_bits;
++  widest_int nonzero_bits;
  };
  
  
  enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
  
  /* Sets the value range to SSA.  */
- extern void set_range_info (tree ssa, widest_int min, widest_int max);
 -extern void set_range_info (tree, double_int, double_int);
++extern void set_range_info (tree, widest_int, widest_int);
  /* Gets the value range from SSA.  */
- extern enum value_range_type  get_range_info (tree name, widest_int *min,
-                                             widest_int *max);
 -extern enum value_range_type get_range_info (const_tree, double_int *,
 -                                           double_int *);
 -extern void set_nonzero_bits (tree, double_int);
 -extern double_int get_nonzero_bits (const_tree);
++extern enum value_range_type get_range_info (const_tree, widest_int *,
++                                           widest_int *);
++extern void set_nonzero_bits (tree, widest_int);
++extern widest_int get_nonzero_bits (const_tree);
  extern void init_ssanames (struct function *, int);
  extern void fini_ssanames (void);
  extern void ssanames_print_statistics (void);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index e92222324793d838efa79088d115ab96c753144d,099880488bc41587c467f8aa1b354eb3b9d0f590..5075246a19b05f87b750f1d68737b228ebee0b5b
@@@ -2256,18 -2259,48 +2259,48 @@@ vect_recog_divmod_pattern (vec<gimple> 
        else
        t3 = t2;
  
-       /* t4 = oprnd0 >> (prec - 1);  */
-       t4 = vect_recog_temp_ssa_var (itype, NULL);
-       def_stmt
-       = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0,
-                                       build_int_cst (itype, prec - 1));
-       append_pattern_def_seq (stmt_vinfo, def_stmt);
 -      double_int oprnd0_min, oprnd0_max;
++      widest_int oprnd0_min, oprnd0_max;
+       int msb = 1;
+       if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE)
+       {
 -        if (!oprnd0_min.is_negative ())
++        if (!wi::neg_p (oprnd0_min))
+           msb = 0;
 -        else if (oprnd0_max.is_negative ())
++        else if (wi::neg_p (oprnd0_max))
+           msb = -1;
+       }
  
-       /* q = t3 - t4;  or q = t4 - t3;  */
-       q = vect_recog_temp_ssa_var (itype, NULL);
-       pattern_stmt
-       = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3,
-                                       d < 0 ? t3 : t4);
+       if (msb == 0 && d >= 0)
+       {
+         /* q = t3;  */
+         q = t3;
+         pattern_stmt = def_stmt;
+       }
+       else
+       {
+         /* t4 = oprnd0 >> (prec - 1);
+            or if we know from VRP that oprnd0 >= 0
+            t4 = 0;
+            or if we know from VRP that oprnd0 < 0
+            t4 = -1;  */
+         append_pattern_def_seq (stmt_vinfo, def_stmt);
+         t4 = vect_recog_temp_ssa_var (itype, NULL);
+         if (msb != 1)
+           def_stmt
+             = gimple_build_assign_with_ops (INTEGER_CST,
+                                             t4, build_int_cst (itype, msb),
+                                             NULL_TREE);
+         else
+           def_stmt
+             = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0,
+                                             build_int_cst (itype, prec - 1));
+         append_pattern_def_seq (stmt_vinfo, def_stmt);
+         /* q = t3 - t4;  or q = t4 - t3;  */
+         q = vect_recog_temp_ssa_var (itype, NULL);
+         pattern_stmt
+           = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3,
+                                           d < 0 ? t3 : t4);
+       }
      }
  
    if (rhs_code == TRUNC_MOD_EXPR)
Simple merge
Simple merge
diff --cc gcc/tree-vrp.c
index fa30d1da9975c75721af5591791b58dae33f2965,15cfcb3f5913d0cd9338dd4035e4f3c835cdc3d3..03fb075193d51503e03320646260c17dbd8ca8eb
@@@ -6376,6 -6459,87 +6386,87 @@@ check_all_array_refs (void
      }
  }
  
 -                        & ~tree_to_double_int (cst)));
+ /* Return true if all imm uses of VAR are either in STMT, or
+    feed (optionally through a chain of single imm uses) GIMPLE_COND
+    in basic block COND_BB.  */
+ static bool
+ all_imm_uses_in_stmt_or_feed_cond (tree var, gimple stmt, basic_block cond_bb)
+ {
+   use_operand_p use_p, use2_p;
+   imm_use_iterator iter;
+   FOR_EACH_IMM_USE_FAST (use_p, iter, var)
+     if (USE_STMT (use_p) != stmt)
+       {
+       gimple use_stmt = USE_STMT (use_p);
+       if (is_gimple_debug (use_stmt))
+         continue;
+       while (is_gimple_assign (use_stmt)
+              && single_imm_use (gimple_assign_lhs (use_stmt),
+                                 &use2_p, &use_stmt))
+         ;
+       if (gimple_code (use_stmt) != GIMPLE_COND
+           || gimple_bb (use_stmt) != cond_bb)
+         return false;
+       }
+   return true;
+ }
+ /* Handle
+    _4 = x_3 & 31;
+    if (_4 != 0)
+      goto <bb 6>;
+    else
+      goto <bb 7>;
+    <bb 6>:
+    __builtin_unreachable ();
+    <bb 7>:
+    x_5 = ASSERT_EXPR <x_3, ...>;
+    If x_3 has no other immediate uses (checked by caller),
+    var is the x_3 var from ASSERT_EXPR, we can clear low 5 bits
+    from the non-zero bitmask.  */
+ static void
+ maybe_set_nonzero_bits (basic_block bb, tree var)
+ {
+   edge e = single_pred_edge (bb);
+   basic_block cond_bb = e->src;
+   gimple stmt = last_stmt (cond_bb);
+   tree cst;
+   if (stmt == NULL
+       || gimple_code (stmt) != GIMPLE_COND
+       || gimple_cond_code (stmt) != ((e->flags & EDGE_TRUE_VALUE)
+                                    ? EQ_EXPR : NE_EXPR)
+       || TREE_CODE (gimple_cond_lhs (stmt)) != SSA_NAME
+       || !integer_zerop (gimple_cond_rhs (stmt)))
+     return;
+   stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (stmt));
+   if (!is_gimple_assign (stmt)
+       || gimple_assign_rhs_code (stmt) != BIT_AND_EXPR
+       || TREE_CODE (gimple_assign_rhs2 (stmt)) != INTEGER_CST)
+     return;
+   if (gimple_assign_rhs1 (stmt) != var)
+     {
+       gimple stmt2;
+       if (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME)
+       return;
+       stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
+       if (!gimple_assign_cast_p (stmt2)
+         || gimple_assign_rhs1 (stmt2) != var
+         || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2))
+         || (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt)))
+                             != TYPE_PRECISION (TREE_TYPE (var))))
+       return;
+     }
+   cst = gimple_assign_rhs2 (stmt);
+   set_nonzero_bits (var, (get_nonzero_bits (var)
++                        & ~wi::to_widest (cst)));
+ }
  /* Convert range assertion expressions into the implied copies and
     copy propagate away the copies.  Doing the trivial copy propagation
     here avoids the need to run the full copy propagation pass after
diff --cc gcc/tree.c
index 9344f7f042931fb237daea179a26cf8d8cdaf60c,332751a3a786cc7167b8272ee879155a23b7444f..133dbb16da9117f15877a7ae9d4f3056ae1225cf
@@@ -1284,8 -1221,9 +1289,9 @@@ wide_int_to_tree (tree type, const wide
  
      case POINTER_TYPE:
      case REFERENCE_TYPE:
-       /* Cache NULL pointer.  */
+     case POINTER_BOUNDS_TYPE:
+       /* Cache NULL pointer and zero bounds.  */
 -      if (!hi && !low)
 +      if (cst == 0)
        {
          limit = 1;
          ix = 0;
@@@ -2219,9 -2191,142 +2225,122 @@@ tree_floor_log2 (const_tree expr
    if (TREE_CODE (expr) == COMPLEX_CST)
      return tree_log2 (TREE_REALPART (expr));
  
 -  prec = TYPE_PRECISION (TREE_TYPE (expr));
 -  high = TREE_INT_CST_HIGH (expr);
 -  low = TREE_INT_CST_LOW (expr);
 -
 -  /* First clear all bits that are beyond the type's precision in case
 -     we've been sign extended.  Ignore if type's precision hasn't been set
 -     since what we are doing is setting it.  */
 -
 -  if (prec == HOST_BITS_PER_DOUBLE_INT || prec == 0)
 -    ;
 -  else if (prec > HOST_BITS_PER_WIDE_INT)
 -    high &= ~(HOST_WIDE_INT_M1U << (prec - HOST_BITS_PER_WIDE_INT));
 -  else
 -    {
 -      high = 0;
 -      if (prec < HOST_BITS_PER_WIDE_INT)
 -      low &= ~(HOST_WIDE_INT_M1U << prec);
 -    }
 -
 -  return (high != 0 ? HOST_BITS_PER_WIDE_INT + floor_log2 (high)
 -        : floor_log2 (low));
 +  return wi::floor_log2 (expr);
  }
  
 -      ret1 = tree_to_double_int (expr).trailing_zeros ();
+ /* Return number of known trailing zero bits in EXPR, or, if the value of
+    EXPR is known to be zero, the precision of it's type.  */
+ unsigned int
+ tree_ctz (const_tree expr)
+ {
+   if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
+       && !POINTER_TYPE_P (TREE_TYPE (expr)))
+     return 0;
+   unsigned int ret1, ret2, prec = TYPE_PRECISION (TREE_TYPE (expr));
+   switch (TREE_CODE (expr))
+     {
+     case INTEGER_CST:
 -      ret1 = get_nonzero_bits (expr).trailing_zeros ();
++      ret1 = wi::ctz (expr);
+       return MIN (ret1, prec);
+     case SSA_NAME:
 -      if (host_integerp (TREE_OPERAND (expr, 1), 1)
 -        && ((unsigned HOST_WIDE_INT) tree_low_cst (TREE_OPERAND (expr, 1), 1)
++      ret1 = wi::ctz (get_nonzero_bits (expr));
+       return MIN (ret1, prec);
+     case PLUS_EXPR:
+     case MINUS_EXPR:
+     case BIT_IOR_EXPR:
+     case BIT_XOR_EXPR:
+     case MIN_EXPR:
+     case MAX_EXPR:
+       ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+       if (ret1 == 0)
+       return ret1;
+       ret2 = tree_ctz (TREE_OPERAND (expr, 1));
+       return MIN (ret1, ret2);
+     case POINTER_PLUS_EXPR:
+       ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+       ret2 = tree_ctz (TREE_OPERAND (expr, 1));
+       /* Second operand is sizetype, which could be in theory
+        wider than pointer's precision.  Make sure we never
+        return more than prec.  */
+       ret2 = MIN (ret2, prec);
+       return MIN (ret1, ret2);
+     case BIT_AND_EXPR:
+       ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+       ret2 = tree_ctz (TREE_OPERAND (expr, 1));
+       return MAX (ret1, ret2);
+     case MULT_EXPR:
+       ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+       ret2 = tree_ctz (TREE_OPERAND (expr, 1));
+       return MIN (ret1 + ret2, prec);
+     case LSHIFT_EXPR:
+       ret1 = tree_ctz (TREE_OPERAND (expr, 0));
 -        ret2 = tree_low_cst (TREE_OPERAND (expr, 1), 1);
++      if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1))
++        && ((unsigned HOST_WIDE_INT) tree_to_uhwi (TREE_OPERAND (expr, 1))
+             < (unsigned HOST_WIDE_INT) prec))
+       {
 -      if (host_integerp (TREE_OPERAND (expr, 1), 1)
 -        && ((unsigned HOST_WIDE_INT) tree_low_cst (TREE_OPERAND (expr, 1), 1)
++        ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1));
+         return MIN (ret1 + ret2, prec);
+       }
+       return ret1;
+     case RSHIFT_EXPR:
 -        ret2 = tree_low_cst (TREE_OPERAND (expr, 1), 1);
++      if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1))
++        && ((unsigned HOST_WIDE_INT) tree_to_uhwi (TREE_OPERAND (expr, 1))
+             < (unsigned HOST_WIDE_INT) prec))
+       {
+         ret1 = tree_ctz (TREE_OPERAND (expr, 0));
++        ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1));
+         if (ret1 > ret2)
+           return ret1 - ret2;
+       }
+       return 0;
+     case TRUNC_DIV_EXPR:
+     case CEIL_DIV_EXPR:
+     case FLOOR_DIV_EXPR:
+     case ROUND_DIV_EXPR:
+     case EXACT_DIV_EXPR:
+       if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST
+         && tree_int_cst_sgn (TREE_OPERAND (expr, 1)) == 1)
+       {
+         int l = tree_log2 (TREE_OPERAND (expr, 1));
+         if (l >= 0)
+           {
+             ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+             ret2 = l;
+             if (ret1 > ret2)
+               return ret1 - ret2;
+           }
+       }
+       return 0;
+     CASE_CONVERT:
+       ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+       if (ret1 && ret1 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
+       ret1 = prec;
+       return MIN (ret1, prec);
+     case SAVE_EXPR:
+       return tree_ctz (TREE_OPERAND (expr, 0));
+     case COND_EXPR:
+       ret1 = tree_ctz (TREE_OPERAND (expr, 1));
+       if (ret1 == 0)
+       return 0;
+       ret2 = tree_ctz (TREE_OPERAND (expr, 2));
+       return MIN (ret1, ret2);
+     case COMPOUND_EXPR:
+       return tree_ctz (TREE_OPERAND (expr, 1));
+     case ADDR_EXPR:
+       ret1 = get_pointer_alignment (CONST_CAST_TREE (expr));
+       if (ret1 > BITS_PER_UNIT)
+       {
+         ret1 = ctz_hwi (ret1 / BITS_PER_UNIT);
+         return MIN (ret1, prec);
+       }
+       return 0;
+     default:
+       return 0;
+     }
+ }
  /* Return 1 if EXPR is the real constant zero.  Trailing zeroes matter for
     decimal float constants, so don't return 1 for them.  */
  
diff --cc gcc/tree.def
Simple merge
diff --cc gcc/tree.h
Simple merge
diff --cc gcc/tsan.c
Simple merge
Simple merge
Simple merge
diff --cc gcc/varasm.c
Simple merge