]> 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 --combined gcc/Makefile.in
index add63e3e1cd7ba1a7f81d0bee26a3dee0613c776,cc88fb8347c0e088103d3fcf1c78a0d49373899a..48c6be26246ad2e0e00dc6aff435ef8e56e62bff
@@@ -311,7 -311,7 +311,7 @@@ write_entries_to_file = $(shell rm -f $
  # --------
  
  # Dependency tracking stuff.
- CCDEPMODE = @CCDEPMODE@
+ CXXDEPMODE = @CXXDEPMODE@
  DEPDIR = @DEPDIR@
  depcomp = $(SHELL) $(srcdir)/../depcomp
  
@@@ -868,11 -868,11 +868,11 @@@ RTL_BASE_H = coretypes.h rtl.h rtl.def 
    insn-notes.def $(INPUT_H) $(REAL_H) statistics.h $(VEC_H) \
    $(FIXED_VALUE_H) alias.h $(HASHTAB_H)
  FIXED_VALUE_H = fixed-value.h $(MACHMODE_H) double-int.h
 -RTL_H = $(RTL_BASE_H) $(FLAGS_H) genrtl.h
 +RTL_H = $(RTL_BASE_H) $(FLAGS_H) genrtl.h wide-int.h
  READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
  PARAMS_H = params.h params.def
  BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \
-       gtm-builtins.def sanitizer.def cilkplus.def
+       gtm-builtins.def sanitizer.def cilkplus.def cilk-builtins.def
  INTERNAL_FN_DEF = internal-fn.def
  INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF)
  TREE_CORE_H = tree-core.h coretypes.h all-tree.def tree.def \
@@@ -898,7 -898,7 +898,7 @@@ FUNCTION_H = function.h $(HASHTAB_H) $(
  EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
  OPTABS_H = optabs.h insn-codes.h insn-opinit.h
  REGS_H = regs.h $(MACHMODE_H) hard-reg-set.h
 -CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) double-int.h \
 +CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) double-int.h wide-int.h \
        $(BITMAP_H) sbitmap.h
  IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
  IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H)
@@@ -913,7 -913,7 +913,7 @@@ TIMEVAR_H = timevar.h timevar.de
  INSN_ATTR_H = insn-attr.h insn-attr-common.h $(INSN_ADDR_H)
  INSN_ADDR_H = $(srcdir)/insn-addr.h
  C_COMMON_H = c-family/c-common.h c-family/c-common.def $(TREE_H) \
 -      $(SPLAY_TREE_H) $(CPPLIB_H) $(GGC_H) $(DIAGNOSTIC_CORE_H)
 +      $(SPLAY_TREE_H) $(CPPLIB_H) $(GGC_H) $(DIAGNOSTIC_CORE_H) wide-int.h
  C_PRAGMA_H = c-family/c-pragma.h $(CPPLIB_H)
  C_TREE_H = c/c-tree.h $(C_COMMON_H) $(DIAGNOSTIC_H)
  SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h \
@@@ -931,7 -931,7 +931,7 @@@ TREE_PASS_H = tree-pass.h $(TIMEVAR_H) 
  TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
                $(BITMAP_H) sbitmap.h $(BASIC_BLOCK_H) $(GIMPLE_H) \
                $(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H) \
 -              tree-ssa-alias.h
 +              tree-ssa-alias.h wide-int.h
  TREE_SSA_H = tree-ssa.h $(TREE_FLOW_H)
  PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H)
  TREE_PRETTY_PRINT_H = tree-pretty-print.h $(PRETTY_PRINT_H)
@@@ -941,7 -941,7 +941,7 @@@ DIAGNOSTIC_H = diagnostic.h $(DIAGNOSTI
  C_PRETTY_PRINT_H = c-family/c-pretty-print.h $(PRETTY_PRINT_H) \
        $(C_COMMON_H) $(TREE_H)
  TREE_INLINE_H = tree-inline.h
 -REAL_H = real.h $(MACHMODE_H)
 +REAL_H = real.h $(MACHMODE_H) signop.h
  LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \
                $(CGRAPH_H) $(VEC_H) $(HASH_TABLE_H) $(TREE_H) $(GIMPLE_H) \
                $(GCOV_IO_H) $(DIAGNOSTIC_H) alloc-pool.h pointer-set.h
@@@ -1040,7 -1040,7 +1040,7 @@@ INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(
           $(CLOOGINC) $(ISLINC)
  
  COMPILE.base = $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) -o $@
- ifeq ($(CCDEPMODE),depmode=gcc3)
+ ifeq ($(CXXDEPMODE),depmode=gcc3)
  # Note a subtlety here: we use $(@D) for the directory part, to make
  # things like the go/%.o rule work properly; but we use $(*F) for the
  # file part, as we just want the file part of the stem, not the entire
@@@ -1049,7 -1049,7 +1049,7 @@@ COMPILE = $(COMPILE.base) -MT $@ -MMD -
  POSTCOMPILE = @mv $(@D)/$(DEPDIR)/$(*F).TPo $(@D)/$(DEPDIR)/$(*F).Po
  else
  COMPILE = source='$<' object='$@' libtool=no \
-     DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) $(COMPILE.base)
+     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) $(COMPILE.base)
  POSTCOMPILE =
  endif
  
@@@ -1132,15 -1132,12 +1132,12 @@@ GCC_OBJS = gcc.o ggc-none.
  c-family-warn = $(STRICT_WARN)
  
  # Language-specific object files shared by all C-family front ends.
- # FIXME: tree-mudflap is C-family only, but it is also part of the middle-end.
- # The mudflap machinery should be properly separated from the front ends, and
- # perhaps turned into a plugin.
  C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \
    c-family/c-format.o c-family/c-gimplify.o c-family/c-lex.o \
    c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \
    c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
-   c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o \
-   c-family/array-notation-common.o c-family/c-ubsan.o
+   c-family/c-semantics.o c-family/c-ada-spec.o \
+   c-family/array-notation-common.o c-family/cilk.o c-family/c-ubsan.o
  
  # Language-independent object files.
  # We put the insn-*.o files first so that a parallel make will build
@@@ -1185,6 -1182,7 +1182,7 @@@ OBJS = 
        cgraphbuild.o \
        cgraphunit.o \
        cgraphclones.o \
+       cilk-common.o \
        combine.o \
        combine-stack-adj.o \
        compare-elim.o \
        reg-stack.o \
        regcprop.o \
        reginfo.o \
-       regmove.o \
        regrename.o \
        regstat.o \
        reload.o \
        tree-iterator.o \
        tree-loop-distribution.o \
        tree-nested.o \
-       tree-nomudflap.o \
        tree-nrv.o \
        tree-object-size.o \
        tree-outof-ssa.o \
        vmsdbgout.o \
        vtable-verify.o \
        web.o \
 +      wide-int.o \
 +      wide-int-print.o \
        xcoffout.o \
        $(out_object_file) \
        $(EXTRA_OBJS) \
@@@ -2227,7 -2221,7 +2223,7 @@@ s-tm-texi: build/genhooks$(build_exeext
  GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
    $(host_xm_file_list) \
    $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) $(srcdir)/bitmap.h \
 -  $(srcdir)/alias.h $(srcdir)/coverage.c $(srcdir)/rtl.h \
 +  $(srcdir)/wide-int.h $(srcdir)/alias.h $(srcdir)/coverage.c $(srcdir)/rtl.h \
    $(srcdir)/optabs.h $(srcdir)/tree.h $(srcdir)/tree-core.h \
    $(srcdir)/libfuncs.h $(SYMTAB_H) \
    $(srcdir)/real.h $(srcdir)/function.h $(srcdir)/insn-addr.h $(srcdir)/hwint.h \
    $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
    $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-utils.h \
    $(srcdir)/dbxout.c \
 +  $(srcdir)/signop.h \
    $(srcdir)/dwarf2out.h \
    $(srcdir)/dwarf2asm.c \
    $(srcdir)/dwarf2cfi.c \
    $(srcdir)/sdbout.c $(srcdir)/stor-layout.c \
    $(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
    $(srcdir)/gimple.h \
-   $(srcdir)/tree-mudflap.c $(srcdir)/gimple-ssa.h \
+   $(srcdir)/gimple-ssa.h \
    $(srcdir)/tree-ssanames.c $(srcdir)/tree-eh.c $(srcdir)/tree-ssa-address.c \
    $(srcdir)/tree-cfg.c \
    $(srcdir)/tree-dfa.c \
@@@ -2436,16 -2429,15 +2432,16 @@@ CFLAGS-gengtype-parse.o += -DGENERATOR_
  build/gengtype-parse.o: $(BCONFIG_H)
  
  gengtype-state.o build/gengtype-state.o: gengtype-state.c $(SYSTEM_H) \
 -  gengtype.h errors.h double-int.h version.h $(HASHTAB_H) $(OBSTACK_H) \
 -  $(XREGEX_H)
 +  gengtype.h errors.h double-int.h version.h $(HASHTAB_H)    \
 +  $(OBSTACK_H) $(XREGEX_H)
  gengtype-state.o: $(CONFIG_H)
  CFLAGS-gengtype-state.o += -DGENERATOR_FILE
  build/gengtype-state.o: $(BCONFIG_H)
 -
 +wide-int.h: $(GTM_H) $(TREE_H) hwint.h $(OPTIONS_H)                   \
 +  $(MACHMODE_H) double-int.h dumpfile.h $(REAL_H) signop.h
  gengtype.o build/gengtype.o : gengtype.c $(SYSTEM_H) gengtype.h       \
 -  rtl.def insn-notes.def errors.h double-int.h version.h $(HASHTAB_H) \
 -  $(OBSTACK_H) $(XREGEX_H)
 +  rtl.def insn-notes.def errors.h double-int.h version.h              \
 +  $(HASHTAB_H) $(OBSTACK_H) $(XREGEX_H)
  gengtype.o: $(CONFIG_H)
  CFLAGS-gengtype.o += -DGENERATOR_FILE
  build/gengtype.o: $(BCONFIG_H)
@@@ -3735,7 -3727,7 +3731,7 @@@ TAGS: lang.tag
            incs="$$incs --include $$dir/TAGS.sub";     \
          fi;                                           \
        done;                                           \
 -      etags -o TAGS.sub c-family/*.h c-family/*.c *.h *.c; \
 +      etags -o TAGS.sub c-family/*.h c-family/*.c *.h *.c *.cc; \
        etags --include TAGS.sub $$incs)
  
  # -----------------------------------------------------
index fe64905adab35b7f34c2637474c6dd82a5b3298c,d38660231556fb349ec7cb50e53e947320321e2e..360d31b34c513bf1166eedb7c01674dfb9b5f833
@@@ -837,13 -837,13 +837,13 @@@ gnat_to_gnu_entity (Entity_Id gnat_enti
                align_cap = get_mode_alignment (ptr_mode);
              }
  
 -          if (!host_integerp (TYPE_SIZE (gnu_type), 1)
 +          if (!tree_fits_uhwi_p (TYPE_SIZE (gnu_type))
                || compare_tree_int (TYPE_SIZE (gnu_type), size_cap) > 0)
              align = 0;
            else if (compare_tree_int (TYPE_SIZE (gnu_type), align_cap) > 0)
              align = align_cap;
            else
 -            align = ceil_pow2 (tree_low_cst (TYPE_SIZE (gnu_type), 1));
 +            align = ceil_pow2 (tree_to_uhwi (TYPE_SIZE (gnu_type)));
  
            /* But make sure not to under-align the object.  */
            if (align <= TYPE_ALIGN (gnu_type))
            && const_flag
            && gnu_expr && TREE_CONSTANT (gnu_expr)
            && AGGREGATE_TYPE_P (gnu_type)
 -          && host_integerp (TYPE_SIZE_UNIT (gnu_type), 1)
 +          && tree_fits_uhwi_p (TYPE_SIZE_UNIT (gnu_type))
            && !(TYPE_IS_PADDING_P (gnu_type)
 -               && !host_integerp (TYPE_SIZE_UNIT
 -                                  (TREE_TYPE (TYPE_FIELDS (gnu_type))), 1)))
 +               && !tree_fits_uhwi_p (TYPE_SIZE_UNIT
 +                                     (TREE_TYPE (TYPE_FIELDS (gnu_type))))))
          static_p = true;
  
        /* Now create the variable or the constant and set various flags.  */
          TYPE_PRECISION (gnu_type) = esize;
          TYPE_UNSIGNED (gnu_type) = is_unsigned;
          set_min_and_max_values_for_integral_type (gnu_type, esize,
 -                                                  is_unsigned);
 +                                                  TYPE_SIGN (gnu_type));
          process_attributes (&gnu_type, &attr_list, true, gnat_entity);
          layout_type (gnu_type);
  
                        gnu_size = DECL_SIZE (gnu_old_field);
                        if (RECORD_OR_UNION_TYPE_P (gnu_field_type)
                            && !TYPE_FAT_POINTER_P (gnu_field_type)
 -                          && host_integerp (TYPE_SIZE (gnu_field_type), 1))
 +                          && tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type)))
                          gnu_field_type
                            = make_packable_type (gnu_field_type, true);
                      }
                                                        NULL_TREE))
                  {
                    unsigned int size
 -                    = TREE_INT_CST_LOW (TYPE_SIZE (gnu_return_type));
 +                    = tree_to_hwi (TYPE_SIZE (gnu_return_type));
                    unsigned int i = BITS_PER_UNIT;
                    enum machine_mode mode;
  
  
              /* Consider an alignment as suspicious if the alignment/size
                 ratio is greater or equal to the byte/bit ratio.  */
 -            if (host_integerp (size, 1)
 -                && align >= TREE_INT_CST_LOW (size) * BITS_PER_UNIT)
 +            if (tree_fits_uhwi_p (size)
 +                && align >= tree_to_uhwi (size) * BITS_PER_UNIT)
                post_error_ne ("?suspiciously large alignment specified for&",
                               Expression (Alignment_Clause (gnat_entity)),
                               gnat_entity);
            }
        }
        else if (Is_Atomic (gnat_entity) && !gnu_size
 -             && host_integerp (TYPE_SIZE (gnu_type), 1)
 +             && tree_fits_uhwi_p (TYPE_SIZE (gnu_type))
               && integer_pow2p (TYPE_SIZE (gnu_type)))
        align = MIN (BIGGEST_ALIGNMENT,
 -                   tree_low_cst (TYPE_SIZE (gnu_type), 1));
 +                   tree_to_uhwi (TYPE_SIZE (gnu_type)));
        else if (Is_Atomic (gnat_entity) && gnu_size
 -             && host_integerp (gnu_size, 1)
 +             && tree_fits_uhwi_p (gnu_size)
               && integer_pow2p (gnu_size))
 -      align = MIN (BIGGEST_ALIGNMENT, tree_low_cst (gnu_size, 1));
 +      align = MIN (BIGGEST_ALIGNMENT, tree_to_uhwi (gnu_size));
  
        /* See if we need to pad the type.  If we did, and made a record,
         the name of the new type may be changed.  So get it back for
@@@ -5579,7 -5579,7 +5579,7 @@@ gnat_to_gnu_component_type (Entity_Id g
        && !Strict_Alignment (gnat_type)
        && RECORD_OR_UNION_TYPE_P (gnu_type)
        && !TYPE_FAT_POINTER_P (gnu_type)
 -      && host_integerp (TYPE_SIZE (gnu_type), 1))
 +      && tree_fits_uhwi_p (TYPE_SIZE (gnu_type)))
      gnu_type = make_packable_type (gnu_type, false);
  
    if (Has_Atomic_Components (gnat_array))
@@@ -6503,7 -6503,7 +6503,7 @@@ gnat_to_gnu_field (Entity_Id gnat_field
    if (!needs_strict_alignment
        && RECORD_OR_UNION_TYPE_P (gnu_field_type)
        && !TYPE_FAT_POINTER_P (gnu_field_type)
 -      && host_integerp (TYPE_SIZE (gnu_field_type), 1)
 +      && tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type))
        && (packed == 1
          || (gnu_size
              && (tree_int_cst_lt (gnu_size, TYPE_SIZE (gnu_field_type))
@@@ -7003,13 -7003,11 +7003,11 @@@ components_to_record (tree gnu_record_t
        tree gnu_union_type, gnu_union_name;
        tree this_first_free_pos, gnu_variant_list = NULL_TREE;
        bool union_field_needs_strict_alignment = false;
-       vec <vinfo_t, va_stack> variant_types;
+       stack_vec <vinfo_t, 16> variant_types;
        vinfo_t *gnu_variant;
        unsigned int variants_align = 0;
        unsigned int i;
  
-       vec_stack_alloc (vinfo_t, variant_types, 16);
        if (TREE_CODE (gnu_name) == TYPE_DECL)
        gnu_name = DECL_NAME (gnu_name);
  
          gnu_variant_list = gnu_field;
        }
  
-       /* We are done with the variants.  */
-       variant_types.release ();
        /* Only make the QUAL_UNION_TYPE if there are non-empty variants.  */
        if (gnu_variant_list)
        {
@@@ -7492,9 -7487,11 +7487,9 @@@ annotate_value (tree gnu_size
        if (TREE_CODE (TREE_OPERAND (gnu_size, 1)) == INTEGER_CST)
        {
          tree op1 = TREE_OPERAND (gnu_size, 1);
 -        double_int signed_op1
 -          = tree_to_double_int (op1).sext (TYPE_PRECISION (sizetype));
 -        if (signed_op1.is_negative ())
 +        if (wi::neg_p (op1))
            {
 -            op1 = double_int_to_tree (sizetype, -signed_op1);
 +            op1 = wide_int_to_tree (sizetype, wi::neg (op1));
              pre_op1 = annotate_value (build1 (NEGATE_EXPR, sizetype, op1));
            }
        }
@@@ -8361,7 -8358,7 +8356,7 @@@ create_field_decl_from (tree old_field
  {
    tree t = TREE_VALUE (purpose_member (old_field, pos_list));
    tree pos = TREE_VEC_ELT (t, 0), bitpos = TREE_VEC_ELT (t, 2);
 -  unsigned int offset_align = tree_low_cst (TREE_VEC_ELT (t, 1), 1);
 +  unsigned int offset_align = tree_to_uhwi (TREE_VEC_ELT (t, 1));
    tree new_pos, new_field;
    unsigned int i;
    subst_pair *s;
index b283b561c38bffd290864aa83ccf7efbe582afde,1d76e6aa468e9e5abfe49333dc9093af22346557..118f9f223dc7435a44668ab65814e554941e33a0
@@@ -3246,7 -3246,7 +3246,7 @@@ finalize_nrv (tree fndecl, bitmap nrv, 
    /* Prune also the candidates that are referenced by nested functions.  */
    node = cgraph_get_create_node (fndecl);
    for (node = node->nested; node; node = node->next_nested)
-     walk_tree_without_duplicates (&DECL_SAVED_TREE (node->symbol.decl), prune_nrv_r,
+     walk_tree_without_duplicates (&DECL_SAVED_TREE (node->decl), prune_nrv_r,
                                  &data);
    if (bitmap_empty_p (nrv))
      return;
@@@ -4239,7 -4239,7 +4239,7 @@@ Call_to_gnu (Node_Id gnat_node, tree *g
            gnu_actual
              = unchecked_convert (DECL_ARG_TYPE (gnu_formal),
                                   convert (gnat_type_for_size
 -                                          (TREE_INT_CST_LOW (gnu_size), 1),
 +                                          (tree_to_hwi (gnu_size), 1),
                                            integer_zero_node),
                                   false);
          else
index 0998c5b4a8c767c4722f575227c2cdf671bc80b1,01a60280e630948f9886b37988ffb0e050fcd687..0a65f3694640b4315c3502a0e7412bd54562d0f2
@@@ -771,7 -771,7 +771,7 @@@ make_aligning_type (tree type, unsigne
  tree
  make_packable_type (tree type, bool in_record)
  {
 -  unsigned HOST_WIDE_INT size = tree_low_cst (TYPE_SIZE (type), 1);
 +  unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
    unsigned HOST_WIDE_INT new_size;
    tree new_type, old_field, field_list = NULL_TREE;
    unsigned int align;
  
        /* Do not try to shrink the size if the RM size is not constant.  */
        if (TYPE_CONTAINS_TEMPLATE_P (type)
 -        || !host_integerp (TYPE_ADA_SIZE (type), 1))
 +        || !tree_fits_uhwi_p (TYPE_ADA_SIZE (type)))
        return type;
  
        /* Round the RM size up to a unit boundary to get the minimal size
         for a BLKmode record.  Give up if it's already the size.  */
 -      new_size = TREE_INT_CST_LOW (TYPE_ADA_SIZE (type));
 +      new_size = tree_to_uhwi (TYPE_ADA_SIZE (type));
        new_size = (new_size + BITS_PER_UNIT - 1) & -BITS_PER_UNIT;
        if (new_size == size)
        return type;
  
        if (RECORD_OR_UNION_TYPE_P (new_field_type)
          && !TYPE_FAT_POINTER_P (new_field_type)
 -        && host_integerp (TYPE_SIZE (new_field_type), 1))
 +        && tree_fits_uhwi_p (TYPE_SIZE (new_field_type)))
        new_field_type = make_packable_type (new_field_type, true);
  
        /* However, for the last field in a not already packed record type
@@@ -915,10 -915,10 +915,10 @@@ make_type_from_size (tree type, tree si
  
    /* If size indicates an error, just return TYPE to avoid propagating
       the error.  Likewise if it's too large to represent.  */
 -  if (!size_tree || !host_integerp (size_tree, 1))
 +  if (!size_tree || !tree_fits_uhwi_p (size_tree))
      return type;
  
 -  size = tree_low_cst (size_tree, 1);
 +  size = tree_to_uhwi (size_tree);
  
    switch (TREE_CODE (type))
      {
@@@ -1741,26 -1741,26 +1741,26 @@@ rest_of_record_type_compilation (tree r
  
          if (!pos
              && TREE_CODE (curpos) == MULT_EXPR
 -            && host_integerp (TREE_OPERAND (curpos, 1), 1))
 +            && tree_fits_uhwi_p (TREE_OPERAND (curpos, 1)))
            {
              tree offset = TREE_OPERAND (curpos, 0);
 -            align = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
 +            align = tree_to_uhwi (TREE_OPERAND (curpos, 1));
              align = scale_by_factor_of (offset, align);
              last_pos = round_up (last_pos, align);
              pos = compute_related_constant (curpos, last_pos);
            }
          else if (!pos
                   && TREE_CODE (curpos) == PLUS_EXPR
 -                 && host_integerp (TREE_OPERAND (curpos, 1), 1)
 +                 && tree_fits_uhwi_p (TREE_OPERAND (curpos, 1))
                   && TREE_CODE (TREE_OPERAND (curpos, 0)) == MULT_EXPR
 -                 && host_integerp
 -                    (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1))
 +                 && tree_fits_uhwi_p
 +                    (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1)))
            {
              tree offset = TREE_OPERAND (TREE_OPERAND (curpos, 0), 0);
              unsigned HOST_WIDE_INT addend
 -              = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
 +              = tree_to_uhwi (TREE_OPERAND (curpos, 1));
              align
 -              = tree_low_cst (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1);
 +              = tree_to_uhwi (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1));
              align = scale_by_factor_of (offset, align);
              align = MIN (align, addend & -addend);
              last_pos = round_up (last_pos, align);
@@@ -2377,8 -2377,8 +2377,8 @@@ create_field_decl (tree field_name, tre
         that an alignment of 0 is taken as infinite.  */
        unsigned int known_align;
  
 -      if (host_integerp (pos, 1))
 -      known_align = tree_low_cst (pos, 1) & - tree_low_cst (pos, 1);
 +      if (tree_fits_uhwi_p (pos))
 +      known_align = tree_to_uhwi (pos) & - tree_to_uhwi (pos);
        else
        known_align = BITS_PER_UNIT;
  
  
        layout_decl (field_decl, known_align);
        SET_DECL_OFFSET_ALIGN (field_decl,
 -                           host_integerp (pos, 1) ? BIGGEST_ALIGNMENT
 +                           tree_fits_uhwi_p (pos) ? BIGGEST_ALIGNMENT
                             : BITS_PER_UNIT);
        pos_from_bit (&DECL_FIELD_OFFSET (field_decl),
                    &DECL_FIELD_BIT_OFFSET (field_decl),
@@@ -2548,8 -2548,8 +2548,8 @@@ invalidate_global_renaming_pointers (vo
  bool
  value_factor_p (tree value, HOST_WIDE_INT factor)
  {
 -  if (host_integerp (value, 1))
 -    return tree_low_cst (value, 1) % factor == 0;
 +  if (tree_fits_uhwi_p (value))
 +    return tree_to_uhwi (value) % factor == 0;
  
    if (TREE_CODE (value) == MULT_EXPR)
      return (value_factor_p (TREE_OPERAND (value, 0), factor)
@@@ -2570,7 -2570,7 +2570,7 @@@ scale_by_factor_of (tree expr, unsigne
    if (TREE_CODE (expr) == BIT_AND_EXPR
        && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST)
      {
 -      unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (TREE_OPERAND (expr, 1));
 +      unsigned HOST_WIDE_INT mask = tree_to_hwi (TREE_OPERAND (expr, 1));
        unsigned int i = 0;
  
        while ((mask & 1) == 0 && i < HOST_BITS_PER_WIDE_INT)
@@@ -2608,16 -2608,16 +2608,16 @@@ potential_alignment_gap (tree prev_fiel
    /* If the distance between the end of prev_field and the beginning of
       curr_field is constant, then there is a gap if the value of this
       constant is not null. */
 -  if (offset && host_integerp (offset, 1))
 +  if (offset && tree_fits_uhwi_p (offset))
      return !integer_zerop (offset);
  
    /* If the size and position of the previous field are constant,
       then check the sum of this size and position. There will be a gap
       iff it is not multiple of the current field alignment. */
 -  if (host_integerp (DECL_SIZE (prev_field), 1)
 -      && host_integerp (bit_position (prev_field), 1))
 -    return ((tree_low_cst (bit_position (prev_field), 1)
 -           + tree_low_cst (DECL_SIZE (prev_field), 1))
 +  if (tree_fits_uhwi_p (DECL_SIZE (prev_field))
 +      && tree_fits_uhwi_p (bit_position (prev_field)))
 +    return ((tree_to_uhwi (bit_position (prev_field))
 +           + tree_to_uhwi (DECL_SIZE (prev_field)))
            % DECL_ALIGN (curr_field) != 0);
  
    /* If both the position and size of the previous field are multiples
@@@ -3274,7 -3274,7 +3274,7 @@@ build_vms_descriptor32 (tree type, Mech
      case ENUMERAL_TYPE:
      case BOOLEAN_TYPE:
        if (TYPE_VAX_FLOATING_POINT_P (type))
 -      switch (tree_low_cst (TYPE_DIGITS_VALUE (type), 1))
 +      switch (tree_to_uhwi (TYPE_DIGITS_VALUE (type)))
          {
          case 6:
            dtype = 10;
      case COMPLEX_TYPE:
        if (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
          && TYPE_VAX_FLOATING_POINT_P (type))
 -      switch (tree_low_cst (TYPE_DIGITS_VALUE (type), 1))
 +      switch (tree_to_uhwi (TYPE_DIGITS_VALUE (type)))
          {
          case 6:
            dtype = 12;
@@@ -3575,7 -3575,7 +3575,7 @@@ build_vms_descriptor (tree type, Mechan
      case ENUMERAL_TYPE:
      case BOOLEAN_TYPE:
        if (TYPE_VAX_FLOATING_POINT_P (type))
 -      switch (tree_low_cst (TYPE_DIGITS_VALUE (type), 1))
 +      switch (tree_to_uhwi (TYPE_DIGITS_VALUE (type)))
          {
          case 6:
            dtype = 10;
      case COMPLEX_TYPE:
        if (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
          && TYPE_VAX_FLOATING_POINT_P (type))
 -      switch (tree_low_cst (TYPE_DIGITS_VALUE (type), 1))
 +      switch (tree_to_uhwi (TYPE_DIGITS_VALUE (type)))
          {
          case 6:
            dtype = 12;
@@@ -3869,7 -3869,7 +3869,7 @@@ convert_vms_descriptor64 (tree gnu_type
        tree max_field = DECL_CHAIN (TYPE_FIELDS (template_type));
        tree template_tree, template_addr, aflags, dimct, t, u;
        /* See the head comment of build_vms_descriptor.  */
 -      int iklass = TREE_INT_CST_LOW (DECL_INITIAL (klass));
 +      int iklass = tree_to_hwi (DECL_INITIAL (klass));
        tree lfield, ufield;
        vec<constructor_elt, va_gc> *v;
  
@@@ -4023,7 -4023,7 +4023,7 @@@ convert_vms_descriptor32 (tree gnu_type
        tree max_field = DECL_CHAIN (TYPE_FIELDS (template_type));
        tree template_tree, template_addr, aflags, dimct, t, u;
        /* See the head comment of build_vms_descriptor.  */
 -      int iklass = TREE_INT_CST_LOW (DECL_INITIAL (klass));
 +      int iklass = tree_to_hwi (DECL_INITIAL (klass));
        vec<constructor_elt, va_gc> *v;
  
        /* Convert POINTER to the pointer-to-array type.  */
@@@ -5307,7 -5307,7 +5307,7 @@@ unchecked_convert (tree type, tree expr
                                     GET_MODE_BITSIZE (TYPE_MODE (type))))
      {
        tree rec_type = make_node (RECORD_TYPE);
 -      unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (type));
 +      unsigned HOST_WIDE_INT prec = tree_to_hwi (TYPE_RM_SIZE (type));
        tree field_type, field;
  
        if (TYPE_UNSIGNED (type))
                                     GET_MODE_BITSIZE (TYPE_MODE (etype))))
      {
        tree rec_type = make_node (RECORD_TYPE);
 -      unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (etype));
 +      unsigned HOST_WIDE_INT prec = tree_to_hwi (TYPE_RM_SIZE (etype));
        vec<constructor_elt, va_gc> *v;
        vec_alloc (v, 1);
        tree field_type, field;
@@@ -5633,7 -5633,7 +5633,7 @@@ gnat_write_global_declarations (void
        TREE_STATIC (dummy_global) = 1;
        TREE_ASM_WRITTEN (dummy_global) = 1;
        node = varpool_node_for_decl (dummy_global);
-       node->symbol.force_output = 1;
+       node->force_output = 1;
  
        while (!types_used_by_cur_var_decl->is_empty ())
        {
@@@ -6061,10 -6061,11 +6061,10 @@@ static boo
  get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
  {
    /* Verify the arg number is a constant.  */
 -  if (TREE_CODE (arg_num_expr) != INTEGER_CST
 -      || TREE_INT_CST_HIGH (arg_num_expr) != 0)
 +  if (!cst_fits_uhwi_p (arg_num_expr))
      return false;
  
 -  *valp = TREE_INT_CST_LOW (arg_num_expr);
 +  *valp = tree_to_hwi (arg_num_expr);
    return true;
  }
  
@@@ -6301,7 -6302,7 +6301,7 @@@ handle_vector_size_attribute (tree *nod
  
    size = TREE_VALUE (args);
  
 -  if (!host_integerp (size, 1))
 +  if (!tree_fits_uhwi_p (size))
      {
        warning (OPT_Wattributes, "%qs attribute ignored",
               IDENTIFIER_POINTER (name));
      }
  
    /* Get the vector size (in bytes).  */
 -  vecsize = tree_low_cst (size, 1);
 +  vecsize = tree_to_uhwi (size);
  
    /* We need to provide for vector pointers, vector arrays, and
       functions returning vectors.  For example:
        || (!SCALAR_FLOAT_MODE_P (orig_mode)
          && GET_MODE_CLASS (orig_mode) != MODE_INT
          && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
 -      || !host_integerp (TYPE_SIZE_UNIT (type), 1)
 +      || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
        || TREE_CODE (type) == BOOLEAN_TYPE)
      {
        error ("invalid vector type for attribute %qs",
        return NULL_TREE;
      }
  
 -  if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1))
 +  if (vecsize % tree_to_uhwi (TYPE_SIZE_UNIT (type)))
      {
        error ("vector size not an integral multiple of component size");
        return NULL;
      }
  
    /* Calculate how many units fit in the vector.  */
 -  nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
 +  nunits = vecsize / tree_to_uhwi (TYPE_SIZE_UNIT (type));
    if (nunits & (nunits - 1))
      {
        error ("number of components of the vector not a power of two");
@@@ -6402,7 -6403,7 +6402,7 @@@ handle_vector_type_attribute (tree *nod
       bases, and this attribute is for binding implementors, not end-users, so
       we should never get there from legitimate explicit uses.  */
  
 -  if (!host_integerp (rep_size, 1))
 +  if (!tree_fits_uhwi_p (rep_size))
      return NULL_TREE;
  
    /* Get the element type/mode and check this is something we know
        || (!SCALAR_FLOAT_MODE_P (elem_mode)
          && GET_MODE_CLASS (elem_mode) != MODE_INT
          && !ALL_SCALAR_FIXED_POINT_MODE_P (elem_mode))
 -      || !host_integerp (TYPE_SIZE_UNIT (elem_type), 1))
 +      || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (elem_type)))
      {
        error ("invalid element type for attribute %qs",
             IDENTIFIER_POINTER (name));
  
    /* Sanity check the vector size and element type consistency.  */
  
 -  vec_bytes = tree_low_cst (rep_size, 1);
 +  vec_bytes = tree_to_uhwi (rep_size);
  
 -  if (vec_bytes % tree_low_cst (TYPE_SIZE_UNIT (elem_type), 1))
 +  if (vec_bytes % tree_to_uhwi (TYPE_SIZE_UNIT (elem_type)))
      {
        error ("vector size not an integral multiple of component size");
        return NULL;
        return NULL;
      }
  
 -  vec_units = vec_bytes / tree_low_cst (TYPE_SIZE_UNIT (elem_type), 1);
 +  vec_units = vec_bytes / tree_to_uhwi (TYPE_SIZE_UNIT (elem_type));
    if (vec_units & (vec_units - 1))
      {
        error ("number of components of the vector not a power of two");
diff --combined gcc/alias.c
index 7af29b3b664ecac665fe141397821a73fb51b7a0,1736169b476f0c9052fc587851d1ed5ec81e0479..8a66d2baa449bf90561693445e03c92d5c7aa8ae
@@@ -40,11 -40,11 +40,11 @@@ along with GCC; see the file COPYING3
  #include "timevar.h"
  #include "dumpfile.h"
  #include "target.h"
- #include "cgraph.h"
  #include "df.h"
  #include "tree-ssa-alias.h"
  #include "pointer-set.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
  
  /* The aliasing API provided here solves related but different problems:
  
@@@ -338,10 -338,9 +338,10 @@@ ao_ref_from_mem (ao_ref *ref, const_rt
    if (MEM_EXPR (mem) != get_spill_slot_decl (false)
        && (ref->offset < 0
          || (DECL_P (ref->base)
 -            && (!host_integerp (DECL_SIZE (ref->base), 1)
 -                || (TREE_INT_CST_LOW (DECL_SIZE ((ref->base)))
 -                    < (unsigned HOST_WIDE_INT)(ref->offset + ref->size))))))
 +            && (DECL_SIZE (ref->base) == NULL_TREE
 +                || TREE_CODE (DECL_SIZE (ref->base)) != INTEGER_CST
 +                || wi::ltu_p (DECL_SIZE (ref->base),
 +                              ref->offset + ref->size)))))
      return false;
  
    return true;
@@@ -1542,7 -1541,9 +1542,7 @@@ rtx_equal_for_memref_p (const_rtx x, co
  
      case VALUE:
      CASE_CONST_UNIQUE:
 -      /* There's no need to compare the contents of CONST_DOUBLEs or
 -       CONST_INTs because pointer equality is a good enough
 -       comparison for these nodes.  */
 +      /* Pointer equality guarantees equality for these nodes.  */
        return 0;
  
      default:
@@@ -2345,22 -2346,15 +2345,22 @@@ adjust_offset_for_component_ref (tree x
      {
        tree xoffset = component_ref_field_offset (x);
        tree field = TREE_OPERAND (x, 1);
 +      if (TREE_CODE (xoffset) != INTEGER_CST)
 +      {
 +        *known_p = false;
 +        return;
 +      }
  
 -      if (! host_integerp (xoffset, 1))
 +      offset_int woffset
 +      = (wi::to_offset (xoffset)
 +         + wi::udiv_trunc (wi::to_offset (DECL_FIELD_BIT_OFFSET (field)),
 +                           BITS_PER_UNIT));
 +      if (!wi::fits_uhwi_p (woffset))
        {
          *known_p = false;
          return;
        }
 -      *offset += (tree_low_cst (xoffset, 1)
 -                + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
 -                   / BITS_PER_UNIT));
 +      *offset += woffset.to_uhwi ();
  
        x = TREE_OPERAND (x, 0);
      }
@@@ -2981,16 -2975,13 +2981,13 @@@ init_alias_analysis (void
        /* Wipe the reg_seen array clean.  */
        bitmap_clear (reg_seen);
  
-       /* Mark all hard registers which may contain an address.
-        The stack, frame and argument pointers may contain an address.
-        An argument register which can hold a Pmode value may contain
-        an address even if it is not in BASE_REGS.
-        The address expression is VOIDmode for an argument and
-        Pmode for other registers.  */
-       memcpy (new_reg_base_value, static_reg_base_value,
-             FIRST_PSEUDO_REGISTER * sizeof (rtx));
+       /* Initialize the alias information for this pass.  */
+       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if (static_reg_base_value[i])
+         {
+           new_reg_base_value[i] = static_reg_base_value[i];
+           bitmap_set_bit (reg_seen, i);
+         }
  
        /* Walk the insns adding values to the new_reg_base_value array.  */
        for (i = 0; i < rpo_cnt; i++)
diff --combined gcc/asan.c
index 84c603ac5214c3daab12ac1c3d97443a9927fbd0,763c59aaed423d584ed6f8d3c4b61a07f5d768af..5dcc981cd06450ed4dcf8d38940d9a5e534e0715
@@@ -22,9 -22,11 +22,11 @@@ along with GCC; see the file COPYING3
  #include "config.h"
  #include "system.h"
  #include "coretypes.h"
+ #include "tree.h"
  #include "gimple.h"
  #include "tree-iterator.h"
- #include "tree-ssa.h"
+ #include "cgraph.h"
+ #include "tree-ssanames.h"
  #include "tree-pass.h"
  #include "asan.h"
  #include "gimple-pretty-print.h"
@@@ -896,7 -898,7 +898,7 @@@ asan_clear_shadow (rtx shadow_mem, HOST
  
    gcc_assert ((len & 3) == 0);
    top_label = gen_label_rtx ();
-   addr = force_reg (Pmode, XEXP (shadow_mem, 0));
+   addr = copy_to_mode_reg (Pmode, XEXP (shadow_mem, 0));
    shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0);
    end = force_reg (Pmode, plus_constant (Pmode, addr, len));
    emit_label (top_label);
@@@ -1996,7 -1998,7 +1998,7 @@@ asan_add_global (tree decl, tree type, 
    CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
                          fold_convert (const_ptr_type_node,
                                        build_fold_addr_expr (refdecl)));
 -  size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
 +  size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
    CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
    size += asan_red_zone_size (size);
    CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
@@@ -2019,6 -2021,9 +2021,9 @@@ initialize_sanitizer_builtins (void
    tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE);
    tree BT_FN_VOID_PTR
      = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+   tree BT_FN_VOID_PTR_PTR
+     = build_function_type_list (void_type_node, ptr_type_node,
+                               ptr_type_node, NULL_TREE);
    tree BT_FN_VOID_PTR_PTR_PTR
      = build_function_type_list (void_type_node, ptr_type_node,
                                ptr_type_node, ptr_type_node, NULL_TREE);
@@@ -2173,8 -2178,8 +2178,8 @@@ asan_finish_file (void
    tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT);
    append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
    FOR_EACH_DEFINED_VARIABLE (vnode)
-     if (TREE_ASM_WRITTEN (vnode->symbol.decl)
-       && asan_protect_global (vnode->symbol.decl))
+     if (TREE_ASM_WRITTEN (vnode->decl)
+       && asan_protect_global (vnode->decl))
        ++gcount;
    htab_t const_desc_htab = constant_pool_htab ();
    htab_traverse (const_desc_htab, count_string_csts, &gcount);
        DECL_IGNORED_P (var) = 1;
        vec_alloc (v, gcount);
        FOR_EACH_DEFINED_VARIABLE (vnode)
-       if (TREE_ASM_WRITTEN (vnode->symbol.decl)
-           && asan_protect_global (vnode->symbol.decl))
-         asan_add_global (vnode->symbol.decl, TREE_TYPE (type), v);
+       if (TREE_ASM_WRITTEN (vnode->decl)
+           && asan_protect_global (vnode->decl))
+         asan_add_global (vnode->decl, TREE_TYPE (type), v);
        struct asan_add_string_csts_data aascd;
        aascd.type = TREE_TYPE (type);
        aascd.v = v;
diff --combined gcc/builtins.c
index 77670f10fb1b845a94577129de59fee005c66282,f84789e6a59f3d27acf7e6dab4e1e017dff82bd8..1c3398353df66c8b5ef9106f7f9397a8236d60b8
@@@ -43,11 -43,13 +43,13 @@@ along with GCC; see the file COPYING3
  #include "target.h"
  #include "langhooks.h"
  #include "basic-block.h"
- #include "tree-ssa.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "value-prof.h"
  #include "diagnostic-core.h"
  #include "builtins.h"
  #include "ubsan.h"
+ #include "cilk.h"
  
  
  static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
@@@ -234,6 -236,10 +236,10 @@@ is_builtin_name (const char *name
      return true;
    if (strncmp (name, "__atomic_", 9) == 0)
      return true;
+   if (flag_enable_cilkplus 
+       && (!strcmp (name, "__cilkrts_detach")   
+         || !strcmp (name, "__cilkrts_pop_frame")))
+     return true;
    return false;
  }
  
@@@ -308,7 -314,7 +314,7 @@@ get_object_alignment_2 (tree exp, unsig
    tree offset;
    enum machine_mode mode;
    int unsignedp, volatilep;
-   unsigned int inner, align = BITS_PER_UNIT;
+   unsigned int align = BITS_PER_UNIT;
    bool known_alignment = false;
  
    /* Get the innermost object and the constant (bitpos) and possibly
        if (TREE_CODE (addr) == BIT_AND_EXPR
          && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
        {
 -        align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
 -                  & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
 +        align = (tree_to_hwi (TREE_OPERAND (addr, 1))
 +                 & -tree_to_hwi (TREE_OPERAND (addr, 1)));
          align *= BITS_PER_UNIT;
          addr = TREE_OPERAND (addr, 0);
        }
            {
              unsigned HOST_WIDE_INT step = 1;
              if (TMR_STEP (exp))
 -              step = TREE_INT_CST_LOW (TMR_STEP (exp));
 +              step = tree_to_hwi (TMR_STEP (exp));
              align = MIN (align, (step & -step) * BITS_PER_UNIT);
            }
          if (TMR_INDEX2 (exp))
          bitpos += ptr_bitpos;
          if (TREE_CODE (exp) == MEM_REF
              || TREE_CODE (exp) == TARGET_MEM_REF)
 -          bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
 +          bitpos += mem_ref_offset (exp).to_short_addr () * BITS_PER_UNIT;
        }
      }
    else if (TREE_CODE (exp) == STRING_CST)
  
    /* If there is a non-constant offset part extract the maximum
       alignment that can prevail.  */
-   inner = ~0U;
-   while (offset)
+   if (offset)
      {
-       tree next_offset;
-       if (TREE_CODE (offset) == PLUS_EXPR)
+       int trailing_zeros = tree_ctz (offset);
+       if (trailing_zeros < HOST_BITS_PER_INT)
        {
-         next_offset = TREE_OPERAND (offset, 0);
-         offset = TREE_OPERAND (offset, 1);
+         unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
+         if (inner)
+           align = MIN (align, inner);
        }
-       else
-       next_offset = NULL;
-       if (tree_fits_uhwi_p (offset))
-       {
-         /* Any overflow in calculating offset_bits won't change
-            the alignment.  */
-         unsigned offset_bits
-           = ((unsigned) tree_to_uhwi (offset) * BITS_PER_UNIT);
-         if (offset_bits)
-           inner = MIN (inner, (offset_bits & -offset_bits));
-       }
-       else if (TREE_CODE (offset) == MULT_EXPR
-              && tree_fits_uhwi_p (TREE_OPERAND (offset, 1)))
-       {
-         /* Any overflow in calculating offset_factor won't change
-            the alignment.  */
-         unsigned offset_factor
-           = ((unsigned) tree_to_uhwi (TREE_OPERAND (offset, 1))
-              * BITS_PER_UNIT);
-         if (offset_factor)
-           inner = MIN (inner, (offset_factor & -offset_factor));
-       }
-       else
-       {
-         inner = MIN (inner, BITS_PER_UNIT);
-         break;
-       }
-       offset = next_offset;
      }
-   /* Alignment is innermost object alignment adjusted by the constant
-      and non-constant offset parts.  */
-   align = MIN (align, inner);
  
    *alignp = align;
    *bitposp = bitpos & (*alignp - 1);
@@@ -536,7 -508,7 +508,7 @@@ get_pointer_alignment_1 (tree exp, unsi
    else if (TREE_CODE (exp) == INTEGER_CST)
      {
        *alignp = BIGGEST_ALIGNMENT;
 -      *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
 +      *bitposp = ((tree_to_hwi (exp) * BITS_PER_UNIT)
                  & (BIGGEST_ALIGNMENT - 1));
        return true;
      }
@@@ -645,10 -617,10 +617,10 @@@ c_strlen (tree src, int only_value
       a null character if we can represent it as a single HOST_WIDE_INT.  */
    if (offset_node == 0)
      offset = 0;
 -  else if (! host_integerp (offset_node, 0))
 +  else if (!tree_fits_shwi_p (offset_node))
      offset = -1;
    else
 -    offset = tree_low_cst (offset_node, 0);
 +    offset = tree_to_shwi (offset_node);
  
    /* If the offset is known to be out of bounds, warn, and call strlen at
       runtime.  */
@@@ -686,30 -658,27 +658,30 @@@ c_getstr (tree src
  
    if (offset_node == 0)
      return TREE_STRING_POINTER (src);
 -  else if (!host_integerp (offset_node, 1)
 +  else if (!tree_fits_uhwi_p (offset_node)
           || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
      return 0;
  
 -  return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
 +  return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node);
  }
  
 -/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
 +/* Return a constant integer corresponding to target reading
     GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
  
  static rtx
  c_readstr (const char *str, enum machine_mode mode)
  {
 -  HOST_WIDE_INT c[2];
    HOST_WIDE_INT ch;
    unsigned int i, j;
 +  HOST_WIDE_INT tmp[MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT];
 +  unsigned int len = (GET_MODE_PRECISION (mode) + HOST_BITS_PER_WIDE_INT - 1)
 +    / HOST_BITS_PER_WIDE_INT;
 +
 +  for (i = 0; i < len; i++)
 +    tmp[i] = 0;
  
    gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
  
 -  c[0] = 0;
 -  c[1] = 0;
    ch = 1;
    for (i = 0; i < GET_MODE_SIZE (mode); i++)
      {
          && GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
        j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
        j *= BITS_PER_UNIT;
 -      gcc_assert (j < HOST_BITS_PER_DOUBLE_INT);
  
        if (ch)
        ch = (unsigned char) str[i];
 -      c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
 +      tmp[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
      }
 -  return immed_double_const (c[0], c[1], mode);
 +  
 +  wide_int c = wide_int::from_array (tmp, len, GET_MODE_PRECISION (mode));
 +  return immed_wide_int_const (c, mode);
  }
  
  /* Cast a target constant CST to target CHAR and if that value fits into
@@@ -743,9 -711,7 +715,9 @@@ target_char_cast (tree cst, char *p
        || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
      return 1;
  
 -  val = TREE_INT_CST_LOW (cst);
 +  /* Do not care if it fits or not right here.  */
 +  val = tree_to_hwi (cst);
 +
    if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
      val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
  
@@@ -3207,7 -3173,7 +3179,7 @@@ expand_builtin_mempcpy_args (tree dest
        return NULL_RTX;
  
        /* If LEN is not constant, call the normal function.  */
 -      if (! host_integerp (len, 1))
 +      if (! tree_fits_uhwi_p (len))
        return NULL_RTX;
  
        len_rtx = expand_normal (len);
@@@ -3442,7 -3408,7 +3414,7 @@@ expand_builtin_strncpy (tree exp, rtx t
        tree slen = c_strlen (src, 1);
  
        /* We must be passed a constant len and src parameter.  */
 -      if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
 +      if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
        return NULL_RTX;
  
        slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
          const char *p = c_getstr (src);
          rtx dest_mem;
  
 -        if (!p || dest_align == 0 || !host_integerp (len, 1)
 -            || !can_store_by_pieces (tree_low_cst (len, 1),
 +        if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
 +            || !can_store_by_pieces (tree_to_uhwi (len),
                                       builtin_strncpy_read_str,
                                       CONST_CAST (char *, p),
                                       dest_align, false))
            return NULL_RTX;
  
          dest_mem = get_memory_rtx (dest, len);
 -        store_by_pieces (dest_mem, tree_low_cst (len, 1),
 +        store_by_pieces (dest_mem, tree_to_uhwi (len),
                           builtin_strncpy_read_str,
                           CONST_CAST (char *, p), dest_align, false, 0);
          dest_mem = force_operand (XEXP (dest_mem, 0), target);
@@@ -3597,13 -3563,13 +3569,13 @@@ expand_builtin_memset_args (tree dest, 
         * the coefficients by pieces (in the required modes).
         * We can't pass builtin_memset_gen_str as that emits RTL.  */
        c = 1;
 -      if (host_integerp (len, 1)
 -        && can_store_by_pieces (tree_low_cst (len, 1),
 +      if (tree_fits_uhwi_p (len)
 +        && can_store_by_pieces (tree_to_uhwi (len),
                                  builtin_memset_read_str, &c, dest_align,
                                  true))
        {
          val_rtx = force_reg (val_mode, val_rtx);
 -        store_by_pieces (dest_mem, tree_low_cst (len, 1),
 +        store_by_pieces (dest_mem, tree_to_uhwi (len),
                           builtin_memset_gen_str, val_rtx, dest_align,
                           true, 0);
        }
  
    if (c)
      {
 -      if (host_integerp (len, 1)
 -        && can_store_by_pieces (tree_low_cst (len, 1),
 +      if (tree_fits_uhwi_p (len)
 +        && can_store_by_pieces (tree_to_uhwi (len),
                                  builtin_memset_read_str, &c, dest_align,
                                  true))
 -      store_by_pieces (dest_mem, tree_low_cst (len, 1),
 +      store_by_pieces (dest_mem, tree_to_uhwi (len),
                         builtin_memset_read_str, &c, dest_align, true, 0);
        else if (!set_storage_via_setmem (dest_mem, len_rtx,
                                        gen_int_mode (c, val_mode),
@@@ -4239,110 -4205,6 +4211,6 @@@ expand_builtin_va_start (tree exp
    return const0_rtx;
  }
  
- /* Return a dummy expression of type TYPE in order to keep going after an
-    error.  */
- static tree
- dummy_object (tree type)
- {
-   tree t = build_int_cst (build_pointer_type (type), 0);
-   return build2 (MEM_REF, type, t, t);
- }
- /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
-    builtin function, but a very special sort of operator.  */
- enum gimplify_status
- gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
- {
-   tree promoted_type, have_va_type;
-   tree valist = TREE_OPERAND (*expr_p, 0);
-   tree type = TREE_TYPE (*expr_p);
-   tree t;
-   location_t loc = EXPR_LOCATION (*expr_p);
-   /* Verify that valist is of the proper type.  */
-   have_va_type = TREE_TYPE (valist);
-   if (have_va_type == error_mark_node)
-     return GS_ERROR;
-   have_va_type = targetm.canonical_va_list_type (have_va_type);
-   if (have_va_type == NULL_TREE)
-     {
-       error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
-       return GS_ERROR;
-     }
-   /* Generate a diagnostic for requesting data of a type that cannot
-      be passed through `...' due to type promotion at the call site.  */
-   if ((promoted_type = lang_hooks.types.type_promotes_to (type))
-          != type)
-     {
-       static bool gave_help;
-       bool warned;
-       /* Unfortunately, this is merely undefined, rather than a constraint
-        violation, so we cannot make this an error.  If this call is never
-        executed, the program is still strictly conforming.  */
-       warned = warning_at (loc, 0,
-                          "%qT is promoted to %qT when passed through %<...%>",
-                          type, promoted_type);
-       if (!gave_help && warned)
-       {
-         gave_help = true;
-         inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
-                 promoted_type, type);
-       }
-       /* We can, however, treat "undefined" any way we please.
-        Call abort to encourage the user to fix the program.  */
-       if (warned)
-       inform (loc, "if this code is reached, the program will abort");
-       /* Before the abort, allow the evaluation of the va_list
-        expression to exit or longjmp.  */
-       gimplify_and_add (valist, pre_p);
-       t = build_call_expr_loc (loc,
-                              builtin_decl_implicit (BUILT_IN_TRAP), 0);
-       gimplify_and_add (t, pre_p);
-       /* This is dead code, but go ahead and finish so that the
-        mode of the result comes out right.  */
-       *expr_p = dummy_object (type);
-       return GS_ALL_DONE;
-     }
-   else
-     {
-       /* Make it easier for the backends by protecting the valist argument
-        from multiple evaluations.  */
-       if (TREE_CODE (have_va_type) == ARRAY_TYPE)
-       {
-         /* For this case, the backends will be expecting a pointer to
-            TREE_TYPE (abi), but it's possible we've
-            actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
-            So fix it.  */
-         if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
-           {
-             tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
-             valist = fold_convert_loc (loc, p1,
-                                        build_fold_addr_expr_loc (loc, valist));
-           }
-         gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
-       }
-       else
-       gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
-       if (!targetm.gimplify_va_arg_expr)
-       /* FIXME: Once most targets are converted we should merely
-          assert this is non-null.  */
-       return GS_ALL_DONE;
-       *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
-       return GS_OK;
-     }
- }
  /* Expand EXP, a call to __builtin_va_end.  */
  
  static rtx
@@@ -4422,7 -4284,7 +4290,7 @@@ expand_builtin_frame_address (tree fnde
    if (call_expr_nargs (exp) == 0)
      /* Warning about missing arg was already issued.  */
      return const0_rtx;
 -  else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
 +  else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
      {
        if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
        error ("invalid argument to %<__builtin_frame_address%>");
      {
        rtx tem
        = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
 -                                    tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
 +                                    tree_to_uhwi (CALL_EXPR_ARG (exp, 0)));
  
        /* Some ports cannot access arbitrary stack frames.  */
        if (tem == NULL)
@@@ -4471,10 -4333,6 +4339,6 @@@ expand_builtin_alloca (tree exp, bool c
    bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
                            == BUILT_IN_ALLOCA_WITH_ALIGN);
  
-   /* Emit normal call if we use mudflap.  */
-   if (flag_mudflap)
-     return NULL_RTX;
    valid_arglist
      = (alloca_with_align
         ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
  
    /* Compute the alignment.  */
    align = (alloca_with_align
 -         ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
 +         ? tree_to_hwi (CALL_EXPR_ARG (exp, 1))
           : BIGGEST_ALIGNMENT);
  
    /* Allocate the desired space.  */
@@@ -4929,12 -4787,12 +4793,12 @@@ expand_builtin_signbit (tree exp, rtx t
  
    if (bitpos < GET_MODE_BITSIZE (rmode))
      {
 -      double_int mask = double_int_zero.set_bit (bitpos);
 +      wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
  
        if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
        temp = gen_lowpart (rmode, temp);
        temp = expand_binop (rmode, and_optab, temp,
 -                         immed_double_int_const (mask, rmode),
 +                         immed_wide_int_const (mask, rmode),
                           NULL_RTX, 1, OPTAB_LIB_WIDEN);
      }
    else
@@@ -5320,7 -5178,7 +5184,7 @@@ expand_builtin_atomic_compare_exchange 
  
    weak = CALL_EXPR_ARG (exp, 3);
    is_weak = false;
 -  if (host_integerp (weak, 0) && tree_low_cst (weak, 0) != 0)
 +  if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
      is_weak = true;
  
    oldval = expect;
@@@ -5754,7 -5612,18 +5618,18 @@@ expand_builtin (tree exp, rtx target, r
        && fcode != BUILT_IN_EXECVE
        && fcode != BUILT_IN_ALLOCA
        && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
-       && fcode != BUILT_IN_FREE)
+       && fcode != BUILT_IN_FREE
+       && fcode != BUILT_IN_CHKP_SET_PTR_BOUNDS
+       && fcode != BUILT_IN_CHKP_INIT_PTR_BOUNDS
+       && fcode != BUILT_IN_CHKP_NULL_PTR_BOUNDS
+       && fcode != BUILT_IN_CHKP_COPY_PTR_BOUNDS
+       && fcode != BUILT_IN_CHKP_NARROW_PTR_BOUNDS
+       && fcode != BUILT_IN_CHKP_STORE_PTR_BOUNDS
+       && fcode != BUILT_IN_CHKP_CHECK_PTR_LBOUNDS
+       && fcode != BUILT_IN_CHKP_CHECK_PTR_UBOUNDS
+       && fcode != BUILT_IN_CHKP_CHECK_PTR_BOUNDS
+       && fcode != BUILT_IN_CHKP_GET_PTR_LBOUND
+       && fcode != BUILT_IN_CHKP_GET_PTR_UBOUND)
      return expand_call (exp, target, ignore);
  
    /* The built-in function expanders test for target == const0_rtx
        expand_builtin_set_thread_pointer (exp);
        return const0_rtx;
  
+     case BUILT_IN_CILK_DETACH:
+       expand_builtin_cilk_detach (exp);
+       return const0_rtx;
+       
+     case BUILT_IN_CILK_POP_FRAME:
+       expand_builtin_cilk_pop_frame (exp);
+       return const0_rtx;
+     case BUILT_IN_CHKP_INIT_PTR_BOUNDS:
+     case BUILT_IN_CHKP_NULL_PTR_BOUNDS:
+     case BUILT_IN_CHKP_COPY_PTR_BOUNDS:
+       return expand_normal (CALL_EXPR_ARG (exp, 0));
+     case BUILT_IN_CHKP_CHECK_PTR_LBOUNDS:
+     case BUILT_IN_CHKP_CHECK_PTR_UBOUNDS:
+     case BUILT_IN_CHKP_CHECK_PTR_BOUNDS:
+     case BUILT_IN_CHKP_SET_PTR_BOUNDS:
+     case BUILT_IN_CHKP_NARROW_PTR_BOUNDS:
+     case BUILT_IN_CHKP_STORE_PTR_BOUNDS:
+     case BUILT_IN_CHKP_GET_PTR_LBOUND:
+     case BUILT_IN_CHKP_GET_PTR_UBOUND:
+       /* We allow user CHKP builtins if Pointer Bounds
+        Checker is off.  */
+       if (!flag_check_pointer_bounds)
+       {
+         if (fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS
+             || fcode == BUILT_IN_CHKP_NARROW_PTR_BOUNDS)
+           return expand_normal (CALL_EXPR_ARG (exp, 0));
+         else if (fcode == BUILT_IN_CHKP_GET_PTR_LBOUND)
+           return expand_normal (size_zero_node);
+         else if (fcode == BUILT_IN_CHKP_GET_PTR_UBOUND)
+           return expand_normal (size_int (-1));
+         else
+           return const0_rtx;
+       }
+       /* FALLTHROUGH */
+     case BUILT_IN_CHKP_BNDMK:
+     case BUILT_IN_CHKP_BNDSTX:
+     case BUILT_IN_CHKP_BNDCL:
+     case BUILT_IN_CHKP_BNDCU:
+     case BUILT_IN_CHKP_BNDLDX:
+     case BUILT_IN_CHKP_BNDRET:
+     case BUILT_IN_CHKP_INTERSECT:
+     case BUILT_IN_CHKP_ARG_BND:
+     case BUILT_IN_CHKP_NARROW:
+     case BUILT_IN_CHKP_EXTRACT_LOWER:
+     case BUILT_IN_CHKP_EXTRACT_UPPER:
+       /* Software implementation of pointers checker is NYI.
+        Target support is required.  */
+       error ("Your target platform does not support -fcheck-pointers");
+       break;
      default:  /* just do library call, if unknown builtin */
        break;
      }
@@@ -7960,8 -7882,8 +7888,8 @@@ fold_builtin_int_roundingfn (location_
        {
          tree itype = TREE_TYPE (TREE_TYPE (fndecl));
          tree ftype = TREE_TYPE (arg);
 -        double_int val;
          REAL_VALUE_TYPE r;
 +        bool fail = false;
  
          switch (DECL_FUNCTION_CODE (fndecl))
            {
              gcc_unreachable ();
            }
  
 -        real_to_integer2 ((HOST_WIDE_INT *)&val.low, &val.high, &r);
 -        if (double_int_fits_to_tree_p (itype, val))
 -          return double_int_to_tree (itype, val);
 +        wide_int val = real_to_integer (&r, &fail, TYPE_PRECISION (itype));
 +        if (!fail)
 +          return wide_int_to_tree (itype, val);
        }
      }
  
@@@ -8022,32 -7944,94 +7950,32 @@@ fold_builtin_bitop (tree fndecl, tree a
    /* Optimize for constant argument.  */
    if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
      {
 -      HOST_WIDE_INT hi, width, result;
 -      unsigned HOST_WIDE_INT lo;
 -      tree type;
 -
 -      type = TREE_TYPE (arg);
 -      width = TYPE_PRECISION (type);
 -      lo = TREE_INT_CST_LOW (arg);
 -
 -      /* Clear all the bits that are beyond the type's precision.  */
 -      if (width > HOST_BITS_PER_WIDE_INT)
 -      {
 -        hi = TREE_INT_CST_HIGH (arg);
 -        if (width < HOST_BITS_PER_DOUBLE_INT)
 -          hi &= ~(HOST_WIDE_INT_M1U << (width - HOST_BITS_PER_WIDE_INT));
 -      }
 -      else
 -      {
 -        hi = 0;
 -        if (width < HOST_BITS_PER_WIDE_INT)
 -          lo &= ~(HOST_WIDE_INT_M1U << width);
 -      }
 +      int result;
  
        switch (DECL_FUNCTION_CODE (fndecl))
        {
        CASE_INT_FN (BUILT_IN_FFS):
 -        if (lo != 0)
 -          result = ffs_hwi (lo);
 -        else if (hi != 0)
 -          result = HOST_BITS_PER_WIDE_INT + ffs_hwi (hi);
 -        else
 -          result = 0;
 +        result = wi::ffs (arg);
          break;
  
        CASE_INT_FN (BUILT_IN_CLZ):
 -        if (hi != 0)
 -          result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
 -        else if (lo != 0)
 -          result = width - floor_log2 (lo) - 1;
 -        else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
 -          result = width;
 +        result = wi::clz (arg);
          break;
  
        CASE_INT_FN (BUILT_IN_CTZ):
 -        if (lo != 0)
 -          result = ctz_hwi (lo);
 -        else if (hi != 0)
 -          result = HOST_BITS_PER_WIDE_INT + ctz_hwi (hi);
 -        else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
 -          result = width;
 +        result = wi::ctz (arg);
          break;
  
        CASE_INT_FN (BUILT_IN_CLRSB):
 -        if (width > 2 * HOST_BITS_PER_WIDE_INT)
 -          return NULL_TREE;
 -        if (width > HOST_BITS_PER_WIDE_INT
 -            && (hi & ((unsigned HOST_WIDE_INT) 1
 -                      << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)
 -          {
 -            hi = ~hi & ~(HOST_WIDE_INT_M1U
 -                         << (width - HOST_BITS_PER_WIDE_INT - 1));
 -            lo = ~lo;
 -          }
 -        else if (width <= HOST_BITS_PER_WIDE_INT
 -                 && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
 -          lo = ~lo & ~(HOST_WIDE_INT_M1U << (width - 1));
 -        if (hi != 0)
 -          result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT;
 -        else if (lo != 0)
 -          result = width - floor_log2 (lo) - 2;
 -        else
 -          result = width - 1;
 +        result = wi::clrsb (arg);
          break;
  
        CASE_INT_FN (BUILT_IN_POPCOUNT):
 -        result = 0;
 -        while (lo)
 -          result++, lo &= lo - 1;
 -        while (hi)
 -          result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
 +        result = wi::popcount (arg);
          break;
  
        CASE_INT_FN (BUILT_IN_PARITY):
 -        result = 0;
 -        while (lo)
 -          result++, lo &= lo - 1;
 -        while (hi)
 -          result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
 -        result &= 1;
 +        result = wi::parity (arg);
          break;
  
        default:
@@@ -8071,24 -8055,49 +7999,24 @@@ fold_builtin_bswap (tree fndecl, tree a
    /* Optimize constant value.  */
    if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
      {
 -      HOST_WIDE_INT hi, width, r_hi = 0;
 -      unsigned HOST_WIDE_INT lo, r_lo = 0;
        tree type = TREE_TYPE (TREE_TYPE (fndecl));
  
 -      width = TYPE_PRECISION (type);
 -      lo = TREE_INT_CST_LOW (arg);
 -      hi = TREE_INT_CST_HIGH (arg);
 -
        switch (DECL_FUNCTION_CODE (fndecl))
        {
          case BUILT_IN_BSWAP16:
          case BUILT_IN_BSWAP32:
          case BUILT_IN_BSWAP64:
            {
 -            int s;
 -
 -            for (s = 0; s < width; s += 8)
 -              {
 -                int d = width - s - 8;
 -                unsigned HOST_WIDE_INT byte;
 -
 -                if (s < HOST_BITS_PER_WIDE_INT)
 -                  byte = (lo >> s) & 0xff;
 -                else
 -                  byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
 -
 -                if (d < HOST_BITS_PER_WIDE_INT)
 -                  r_lo |= byte << d;
 -                else
 -                  r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
 -              }
 +            signop sgn = TYPE_SIGN (type);
 +            tree result = 
 +              wide_int_to_tree (type,
 +                                wide_int::from (arg, TYPE_PRECISION (type),
 +                                                sgn).bswap ());
 +            return result;
            }
 -
 -          break;
 -
        default:
          gcc_unreachable ();
        }
 -
 -      if (width < HOST_BITS_PER_WIDE_INT)
 -      return build_int_cst (type, r_lo);
 -      else
 -      return build_int_cst_wide (type, r_lo, r_hi);
      }
  
    return NULL_TREE;
@@@ -8150,7 -8159,7 +8078,7 @@@ fold_builtin_logarithm (location_t loc
            /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
            {
              REAL_VALUE_TYPE dconst10;
 -            real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
 +            real_from_integer (&dconst10, VOIDmode, 10, SIGNED);
              x = build_real (type, dconst10);
            }
            exponent = CALL_EXPR_ARG (arg, 0);
@@@ -8303,7 -8312,7 +8231,7 @@@ fold_builtin_pow (location_t loc, tree 
  
        /* Check for an integer exponent.  */
        n = real_to_integer (&c);
 -      real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
 +      real_from_integer (&cint, VOIDmode, n, SIGNED);
        if (real_identical (&c, &cint))
        {
          /* Attempt to evaluate pow at compile-time, unless this should
@@@ -8401,9 -8410,9 +8329,9 @@@ fold_builtin_powi (location_t loc, tre
    if (real_onep (arg0))
      return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
  
 -  if (host_integerp (arg1, 0))
 +  if (tree_fits_shwi_p (arg1))
      {
 -      HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
 +      HOST_WIDE_INT c = tree_to_shwi (arg1);
  
        /* Evaluate powi at compile-time.  */
        if (TREE_CODE (arg0) == REAL_CST
@@@ -8500,7 -8509,7 +8428,7 @@@ fold_builtin_memset (location_t loc, tr
        || ! validate_arg (len, INTEGER_TYPE))
      return NULL_TREE;
  
 -  if (! host_integerp (len, 1))
 +  if (! tree_fits_uhwi_p (len))
      return NULL_TREE;
  
    /* If the LEN parameter is zero, return DEST.  */
    if (! var_decl_component_p (var))
      return NULL_TREE;
  
 -  length = tree_low_cst (len, 1);
 +  length = tree_to_uhwi (len);
    if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
        || get_pointer_alignment (dest) / BITS_PER_UNIT < length)
      return NULL_TREE;
        if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
        return NULL_TREE;
  
 -      cval = TREE_INT_CST_LOW (c);
 +      cval = tree_to_hwi (c);
        cval &= 0xff;
        cval |= cval << 8;
        cval |= cval << 16;
@@@ -8633,9 -8642,9 +8561,9 @@@ fold_builtin_memory_op (location_t loc
          if (!dest_align || !src_align)
            return NULL_TREE;
          if (readonly_data_expr (src)
 -            || (host_integerp (len, 1)
 +            || (tree_fits_uhwi_p (len)
                  && (MIN (src_align, dest_align) / BITS_PER_UNIT
 -                    >= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1))))
 +                    >= (unsigned HOST_WIDE_INT) tree_to_uhwi (len))))
            {
              tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
              if (!fn)
              destvar = TREE_OPERAND (dest, 0);
              dest_base = get_ref_base_and_extent (destvar, &dest_offset,
                                                   &size, &maxsize);
 -            if (host_integerp (len, 1))
 -              maxsize = tree_low_cst (len, 1);
 +            if (tree_fits_uhwi_p (len))
 +              maxsize = tree_to_uhwi (len);
              else
                maxsize = -1;
              src_offset /= BITS_PER_UNIT;
              else if (TREE_CODE (src_base) == MEM_REF
                       && TREE_CODE (dest_base) == MEM_REF)
                {
 -                double_int off;
                  if (! operand_equal_p (TREE_OPERAND (src_base, 0),
                                         TREE_OPERAND (dest_base, 0), 0))
                    return NULL_TREE;
 -                off = mem_ref_offset (src_base) +
 -                                      double_int::from_shwi (src_offset);
 -                if (!off.fits_shwi ())
 +                offset_int off = mem_ref_offset (src_base) + src_offset;
 +                if (!wi::fits_shwi_p (off))
                    return NULL_TREE;
 -                src_offset = off.low;
 -                off = mem_ref_offset (dest_base) +
 -                                      double_int::from_shwi (dest_offset);
 -                if (!off.fits_shwi ())
 +                src_offset = off.to_shwi ();
 +
 +                off = mem_ref_offset (dest_base) + dest_offset;
 +                if (!wi::fits_shwi_p (off))
                    return NULL_TREE;
 -                dest_offset = off.low;
 +                dest_offset = off.to_shwi ();
                  if (ranges_overlap_p (src_offset, maxsize,
                                        dest_offset, maxsize))
                    return NULL_TREE;
          return NULL_TREE;
        }
  
 -      if (!host_integerp (len, 0))
 +      if (!tree_fits_shwi_p (len))
        return NULL_TREE;
        /* FIXME:
           This logic lose for arguments like (type *)malloc (sizeof (type)),
@@@ -9011,7 -9022,7 +8939,7 @@@ fold_builtin_memchr (location_t loc, tr
        const char *p1;
  
        if (TREE_CODE (arg2) != INTEGER_CST
 -        || !host_integerp (len, 1))
 +        || !tree_fits_uhwi_p (len))
        return NULL_TREE;
  
        p1 = c_getstr (arg1);
          if (target_char_cast (arg2, &c))
            return NULL_TREE;
  
 -        r = (const char *) memchr (p1, c, tree_low_cst (len, 1));
 +        r = (const char *) memchr (p1, c, tree_to_uhwi (len));
  
          if (r == NULL)
            return build_int_cst (TREE_TYPE (arg1), 0);
@@@ -9063,11 -9074,11 +8991,11 @@@ fold_builtin_memcmp (location_t loc, tr
  
    /* If all arguments are constant, and the value of len is not greater
       than the lengths of arg1 and arg2, evaluate at compile-time.  */
 -  if (host_integerp (len, 1) && p1 && p2
 +  if (tree_fits_uhwi_p (len) && p1 && p2
        && compare_tree_int (len, strlen (p1) + 1) <= 0
        && compare_tree_int (len, strlen (p2) + 1) <= 0)
      {
 -      const int r = memcmp (p1, p2, tree_low_cst (len, 1));
 +      const int r = memcmp (p1, p2, tree_to_uhwi (len));
  
        if (r > 0)
        return integer_one_node;
  
    /* If len parameter is one, return an expression corresponding to
       (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
 -  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
 +  if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
      {
        tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
        tree cst_uchar_ptr_node
@@@ -9191,9 -9202,9 +9119,9 @@@ fold_builtin_strncmp (location_t loc, t
    p1 = c_getstr (arg1);
    p2 = c_getstr (arg2);
  
 -  if (host_integerp (len, 1) && p1 && p2)
 +  if (tree_fits_uhwi_p (len) && p1 && p2)
      {
 -      const int i = strncmp (p1, p2, tree_low_cst (len, 1));
 +      const int i = strncmp (p1, p2, tree_to_uhwi (len));
        if (i > 0)
        return integer_one_node;
        else if (i < 0)
  
    /* If len parameter is one, return an expression corresponding to
       (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
 -  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
 +  if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
      {
        tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
        tree cst_uchar_ptr_node
@@@ -9697,7 -9708,7 +9625,7 @@@ fold_builtin_load_exponent (location_t 
        /* If both arguments are constant, then try to evaluate it.  */
        if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
          && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
 -        && host_integerp (arg1, 0))
 +        && tree_fits_shwi_p (arg1))
          {
          /* Bound the maximum adjustment to twice the range of the
             mode's valid exponents.  Use abs to ensure the range is
                 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
  
          /* Get the user-requested adjustment.  */
 -        const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
 +        const HOST_WIDE_INT req_exp_adj = tree_to_shwi (arg1);
  
          /* The requested adjustment must be inside this range.  This
             is a preliminary cap to avoid things like overflow, we
@@@ -12188,7 -12199,7 +12116,7 @@@ fold_builtin_snprintf (location_t loc, 
    if (orig && !validate_arg (orig, POINTER_TYPE))
      return NULL_TREE;
  
 -  if (!host_integerp (destsize, 1))
 +  if (!tree_fits_uhwi_p (destsize))
      return NULL_TREE;
  
    /* Check whether the format is a literal string constant.  */
    if (!init_target_chars ())
      return NULL_TREE;
  
 -  destlen = tree_low_cst (destsize, 1);
 +  destlen = tree_to_uhwi (destsize);
  
    /* If the format doesn't contain % args or %%, use strcpy.  */
    if (strchr (fmt_str, target_percent) == NULL)
        return NULL_TREE;
  
        retval = c_strlen (orig, 1);
 -      if (!retval || !host_integerp (retval, 1))  
 +      if (!retval || !tree_fits_uhwi_p (retval))  
        return NULL_TREE;
  
 -      origlen = tree_low_cst (retval, 1);
 +      origlen = tree_to_uhwi (retval);
        /* We could expand this as
         memcpy (str1, str2, cst - 1); str1[cst - 1] = '\0';
         or to
@@@ -12312,7 -12323,7 +12240,7 @@@ expand_builtin_object_size (tree exp
        return const0_rtx;
      }
  
 -  object_size_type = tree_low_cst (ost, 0);
 +  object_size_type = tree_to_shwi (ost);
  
    return object_size_type < 2 ? constm1_rtx : const0_rtx;
  }
@@@ -12341,10 -12352,10 +12269,10 @@@ expand_builtin_memory_chk (tree exp, rt
    len = CALL_EXPR_ARG (exp, 2);
    size = CALL_EXPR_ARG (exp, 3);
  
 -  if (! host_integerp (size, 1))
 +  if (! tree_fits_uhwi_p (size))
      return NULL_RTX;
  
 -  if (host_integerp (len, 1) || integer_all_onesp (size))
 +  if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
      {
        tree fn;
  
@@@ -12475,22 -12486,22 +12403,22 @@@ maybe_emit_chk_warning (tree exp, enum 
    if (!len || !size)
      return;
  
 -  if (! host_integerp (size, 1) || integer_all_onesp (size))
 +  if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
      return;
  
    if (is_strlen)
      {
        len = c_strlen (len, 1);
 -      if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
 +      if (! len || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size))
        return;
      }
    else if (fcode == BUILT_IN_STRNCAT_CHK)
      {
        tree src = CALL_EXPR_ARG (exp, 1);
 -      if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
 +      if (! src || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size))
        return;
        src = c_strlen (src, 1);
 -      if (! src || ! host_integerp (src, 1))
 +      if (! src || ! tree_fits_uhwi_p (src))
        {
          warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
                      exp, get_callee_fndecl (exp));
        else if (tree_int_cst_lt (src, size))
        return;
      }
 -  else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
 +  else if (! tree_fits_uhwi_p (len) || ! tree_int_cst_lt (size, len))
      return;
  
    warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
@@@ -12523,7 -12534,7 +12451,7 @@@ maybe_emit_sprintf_chk_warning (tree ex
    size = CALL_EXPR_ARG (exp, 2);
    fmt = CALL_EXPR_ARG (exp, 3);
  
 -  if (! host_integerp (size, 1) || integer_all_onesp (size))
 +  if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
      return;
  
    /* Check whether the format is a literal string constant.  */
        return;
  
        len = c_strlen (arg, 1);
 -      if (!len || ! host_integerp (len, 1))
 +      if (!len || ! tree_fits_uhwi_p (len))
        return;
      }
    else
@@@ -12594,7 -12605,6 +12522,7 @@@ fold_builtin_object_size (tree ptr, tre
  {
    unsigned HOST_WIDE_INT bytes;
    int object_size_type;
 +  int precision = TYPE_PRECISION (TREE_TYPE (ptr));
  
    if (!validate_arg (ptr, POINTER_TYPE)
        || !validate_arg (ost, INTEGER_TYPE))
        || compare_tree_int (ost, 3) > 0)
      return NULL_TREE;
  
 -  object_size_type = tree_low_cst (ost, 0);
 +  object_size_type = tree_to_shwi (ost);
  
    /* __builtin_object_size doesn't evaluate side-effects in its arguments;
       if there are any side-effects, it returns (size_t) -1 for types 0 and 1
  
    if (TREE_CODE (ptr) == ADDR_EXPR)
      {
 -      bytes = compute_builtin_object_size (ptr, object_size_type);
 -      if (double_int_fits_to_tree_p (size_type_node,
 -                                   double_int::from_uhwi (bytes)))
 -      return build_int_cstu (size_type_node, bytes);
 +      wide_int wbytes 
 +      = wi::uhwi (compute_builtin_object_size (ptr, object_size_type),
 +                  precision);
 +      if (wi::fits_to_tree_p (wbytes, size_type_node))
 +      return wide_int_to_tree (size_type_node, wbytes);
      }
    else if (TREE_CODE (ptr) == SSA_NAME)
      {
         later.  Maybe subsequent passes will help determining
         it.  */
        bytes = compute_builtin_object_size (ptr, object_size_type);
 +      wide_int wbytes = wi::uhwi (bytes, precision);
        if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2 ? -1 : 0)
 -          && double_int_fits_to_tree_p (size_type_node,
 -                                      double_int::from_uhwi (bytes)))
 -      return build_int_cstu (size_type_node, bytes);
 +          && wi::fits_to_tree_p (wbytes, size_type_node))
 +      return wide_int_to_tree (size_type_node, wbytes);
      }
  
    return NULL_TREE;
@@@ -12674,17 -12683,17 +12602,17 @@@ fold_builtin_memory_chk (location_t loc
        }
      }
  
 -  if (! host_integerp (size, 1))
 +  if (! tree_fits_uhwi_p (size))
      return NULL_TREE;
  
    if (! integer_all_onesp (size))
      {
 -      if (! host_integerp (len, 1))
 +      if (! tree_fits_uhwi_p (len))
        {
          /* If LEN is not constant, try MAXLEN too.
             For MAXLEN only allow optimizing into non-_ocs function
             if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
 -        if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
 +        if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
            {
              if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
                {
@@@ -12756,18 -12765,18 +12684,18 @@@ fold_builtin_stxcpy_chk (location_t loc
    if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
      return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
  
 -  if (! host_integerp (size, 1))
 +  if (! tree_fits_uhwi_p (size))
      return NULL_TREE;
  
    if (! integer_all_onesp (size))
      {
        len = c_strlen (src, 1);
 -      if (! len || ! host_integerp (len, 1))
 +      if (! len || ! tree_fits_uhwi_p (len))
        {
          /* If LEN is not constant, try MAXLEN too.
             For MAXLEN only allow optimizing into non-_ocs function
             if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
 -        if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
 +        if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
            {
              if (fcode == BUILT_IN_STPCPY_CHK)
                {
@@@ -12843,17 -12852,17 +12771,17 @@@ fold_builtin_stxncpy_chk (location_t lo
           return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
      }
  
 -  if (! host_integerp (size, 1))
 +  if (! tree_fits_uhwi_p (size))
      return NULL_TREE;
  
    if (! integer_all_onesp (size))
      {
 -      if (! host_integerp (len, 1))
 +      if (! tree_fits_uhwi_p (len))
        {
          /* If LEN is not constant, try MAXLEN too.
             For MAXLEN only allow optimizing into non-_ocs function
             if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
 -        if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
 +        if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
            return NULL_TREE;
        }
        else
@@@ -12892,7 -12901,7 +12820,7 @@@ fold_builtin_strcat_chk (location_t loc
    if (p && *p == '\0')
      return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
  
 -  if (! host_integerp (size, 1) || ! integer_all_onesp (size))
 +  if (! tree_fits_uhwi_p (size) || ! integer_all_onesp (size))
      return NULL_TREE;
  
    /* If __builtin_strcat_chk is used, assume strcat is available.  */
@@@ -12926,15 -12935,15 +12854,15 @@@ fold_builtin_strncat_chk (location_t lo
    else if (integer_zerop (len))
      return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
  
 -  if (! host_integerp (size, 1))
 +  if (! tree_fits_uhwi_p (size))
      return NULL_TREE;
  
    if (! integer_all_onesp (size))
      {
        tree src_len = c_strlen (src, 1);
        if (src_len
 -        && host_integerp (src_len, 1)
 -        && host_integerp (len, 1)
 +        && tree_fits_uhwi_p (src_len)
 +        && tree_fits_uhwi_p (len)
          && ! tree_int_cst_lt (len, src_len))
        {
          /* If LEN >= strlen (SRC), optimize into __strcat_chk.  */
@@@ -12983,7 -12992,7 +12911,7 @@@ fold_builtin_sprintf_chk_1 (location_t 
    if (!validate_arg (fmt, POINTER_TYPE))
      return NULL_TREE;
  
 -  if (! host_integerp (size, 1))
 +  if (! tree_fits_uhwi_p (size))
      return NULL_TREE;
  
    len = NULL_TREE;
              if (validate_arg (arg, POINTER_TYPE))
                {
                  len = c_strlen (arg, 1);
 -                if (! len || ! host_integerp (len, 1))
 +                if (! len || ! tree_fits_uhwi_p (len))
                    len = NULL_TREE;
                }
            }
@@@ -13091,17 -13100,17 +13019,17 @@@ fold_builtin_snprintf_chk_1 (location_
    if (!validate_arg (fmt, POINTER_TYPE))
      return NULL_TREE;
  
 -  if (! host_integerp (size, 1))
 +  if (! tree_fits_uhwi_p (size))
      return NULL_TREE;
  
    if (! integer_all_onesp (size))
      {
 -      if (! host_integerp (len, 1))
 +      if (! tree_fits_uhwi_p (len))
        {
          /* If LEN is not constant, try MAXLEN too.
             For MAXLEN only allow optimizing into non-_ocs function
             if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
 -        if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
 +        if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
            return NULL_TREE;
        }
        else
@@@ -13746,10 -13755,10 +13674,10 @@@ do_mpfr_bessel_n (tree arg1, tree arg2
    /* To proceed, MPFR must exactly represent the target floating point
       format, which only happens when the target base equals two.  */
    if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
 -      && host_integerp (arg1, 0)
 +      && tree_fits_shwi_p (arg1)
        && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
      {
 -      const HOST_WIDE_INT n = tree_low_cst (arg1, 0);
 +      const HOST_WIDE_INT n = tree_to_shwi (arg1);
        const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
  
        if (n == (long)n
index 89379dbe4c8d01a68dafa59c30a996a60dcd1660,3f325e77098776fb4734deaabacc6460726e0da0..bdba8f98ea141a01cc5bbadcdde35ceb064572fa
@@@ -29,35 -29,48 +29,34 @@@ 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 *),
-                     int (*)(tree, cpp_operation));
+                     int (*)(const_tree, cpp_operation));
  static char *to_ada_name (const char *, int *);
  static bool separate_class_package (tree);
  
- #define INDENT(SPACE) do { \
-   int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
+ #define INDENT(SPACE) \
+   do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
  
  #define INDENT_INCR 3
  
+ /* Global hook used to perform C++ queries on nodes.  */
+ static int (*cpp_check) (const_tree, cpp_operation) = NULL;
  /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
     as max length PARAM_LEN of arguments for fun_like macros, and also set
     SUPPORTED to 0 if the macro cannot be mapped to an Ada construct.  */
@@@ -622,11 -635,10 +621,10 @@@ unmark_visited_r (tree *tp, int *walk_s
  }
  
  /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
-    to collect_ada_nodes.  CPP_CHECK is used to perform C++ queries on nodes.  */
+    to collect_ada_nodes.  */
  
  static void
- dump_ada_nodes (pretty_printer *pp, const char *source_file,
-               int (*cpp_check)(tree, cpp_operation))
+ dump_ada_nodes (pretty_printer *pp, const char *source_file)
  {
    int i, j;
    cpp_comment_table *comments;
          if (j == comments->count
              || LOCATION_LINE (decl_sloc (to_dump[i], false))
              <  LOCATION_LINE (comments->entries[j].sloc))
-           print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file);
+           print_generic_ada_decl (pp, to_dump[i++], source_file);
          else
            break;
        }
@@@ -722,18 -734,15 +720,15 @@@ print_comment (pretty_printer *pp, cons
      pp_newline (pp);
  }
  
- /* Prints declaration DECL to PP in Ada syntax. The current source file being
-    handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on
-    nodes.  */
+ /* Print declaration DECL to PP in Ada syntax.  The current source file being
+    handled is SOURCE_FILE.  */
  
  static void
- print_generic_ada_decl (pretty_printer *pp, tree decl,
-                       int (*cpp_check)(tree, cpp_operation),
-                       const char* source_file)
+ print_generic_ada_decl (pretty_printer *pp, tree decl, const char *source_file)
  {
    source_file_base = source_file;
  
-   if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR))
+   if (print_ada_declaration (pp, decl, 0, INDENT_INCR))
      {
        pp_newline (pp);
        pp_newline (pp);
@@@ -927,23 -936,25 +922,25 @@@ get_underlying_decl (tree type
  
  /* Return whether TYPE has static fields.  */
  
- static int
+ static bool
  has_static_fields (const_tree type)
  {
    tree tmp;
  
+   if (!type || !RECORD_OR_UNION_TYPE_P (type))
+     return false;
    for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
-     {
-       if (DECL_NAME (tmp) && TREE_STATIC (tmp))
-       return true;
-     }
+     if (DECL_NAME (tmp) && TREE_STATIC (tmp))
+       return true;
    return false;
  }
  
  /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
     table).  */
  
- static int
+ static bool
  is_tagged_type (const_tree type)
  {
    tree tmp;
    return false;
  }
  
+ /* Return whether TYPE has non-trivial methods, i.e. methods that do something
+    for the objects of TYPE.  In C++, all classes have implicit special methods,
+    e.g. constructors and destructors, but they can be trivial if the type is
+    sufficiently simple.  */
+ static bool
+ has_nontrivial_methods (const_tree type)
+ {
+   tree tmp;
+   if (!type || !RECORD_OR_UNION_TYPE_P (type))
+     return false;
+   /* Only C++ types can have methods.  */
+   if (!cpp_check)
+     return false;
+   /* A non-trivial type has non-trivial special methods.  */
+   if (!cpp_check (type, IS_TRIVIAL))
+     return true;
+   /* If there are user-defined methods, they are deemed non-trivial.  */
+   for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
+     if (!DECL_ARTIFICIAL (tmp))
+       return true;
+   return false;
+ }
  /* Generate a legal Ada name from a C NAME, returning a malloc'd string.
     SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
     NAME.  */
@@@ -1179,15 -1219,8 +1205,8 @@@ to_ada_name (const char *name, int *spa
  static bool
  separate_class_package (tree decl)
  {
-   if (decl) 
-     {
-       tree type = TREE_TYPE (decl);
-       return type
-       && TREE_CODE (type) == RECORD_TYPE
-       && (TYPE_METHODS (type) || has_static_fields (type));
-     }
-   else
-     return false;
+   tree type = TREE_TYPE (decl);
+   return has_nontrivial_methods (type) || has_static_fields (type);
  }
  
  static bool package_prefix = true;
@@@ -1207,7 -1240,6 +1226,6 @@@ pp_ada_tree_identifier (pretty_printer 
  
    /* If the entity is a type and comes from another file, generate "package"
       prefix.  */
    decl = get_underlying_decl (type);
  
    if (decl)
                  case UNION_TYPE:
                  case QUAL_UNION_TYPE:
                  case TYPE_DECL:
-                   {
-                     char *s1 = get_ada_package (xloc.file);
-                     if (package_prefix)
-                       {
-                         append_withs (s1, limited_access);
-                         pp_string (buffer, s1);
-                         pp_dot (buffer);
-                       }
-                     free (s1);
-                   }
+                   if (package_prefix)
+                     {
+                       char *s1 = get_ada_package (xloc.file);
+                       append_withs (s1, limited_access);
+                       pp_string (buffer, s1);
+                       pp_dot (buffer);
+                       free (s1);
+                     }
                    break;
                  default:
                    break;
                }
-               
-               if (separate_class_package (decl))
-                 {
-                   pp_string (buffer, "Class_");
-                   pp_string (buffer, s);
-                   pp_dot (buffer);
-                 }
-             }
+             /* Generate the additional package prefix for C++ classes.  */
+             if (separate_class_package (decl))
+               {
+                 pp_string (buffer, "Class_");
+                 pp_string (buffer, s);
+                 pp_dot (buffer);
+               }
+            }
        }
      }
  
@@@ -1513,15 -1542,13 +1528,13 @@@ dump_ada_function_declaration (pretty_p
              pp_string (buffer, buf);
            }
  
-         dump_generic_ada_node
-           (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true);
+         dump_generic_ada_node (buffer, TREE_TYPE (arg), node, spc, 0, true);
        }
        else
        {
          sprintf (buf, "arg%d : ", num);
          pp_string (buffer, buf);
-         dump_generic_ada_node
-           (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true);
+         dump_generic_ada_node (buffer, TREE_VALUE (arg), node, spc, 0, true);
        }
  
        if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
@@@ -1579,13 -1606,13 +1592,13 @@@ dump_ada_array_domains (pretty_printer 
          first = 0;
  
          if (min)
-           dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true);
+           dump_generic_ada_node (buffer, min, NULL_TREE, spc, 0, true);
          pp_string (buffer, " .. ");
  
          /* If the upper bound is zero, gcc may generate a NULL_TREE
             for TYPE_MAX_VALUE rather than an integer_cst.  */
          if (max)
-           dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true);
+           dump_generic_ada_node (buffer, max, NULL_TREE, spc, 0, true);
          else
            pp_string (buffer, "0");
        }
@@@ -1673,18 -1700,16 +1686,16 @@@ dump_ada_array_type (pretty_printer *bu
        pp_string (buffer, "aliased ");
  
        dump_generic_ada_node
-       (buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true);
+       (buffer, TREE_TYPE (tmp), TREE_TYPE (t), spc, false, true);
      }
  }
  
  /* Dump in BUFFER type names associated with a template, each prepended with
-    '_'.  TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.
-    CPP_CHECK is used to perform C++ queries on nodes.
-    SPC is the indentation level.  */
+    '_'.  TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.  SPC is
+    the indentation level.  */
  
  static void
- dump_template_types (pretty_printer *buffer, tree types,
-                    int (*cpp_check)(tree, cpp_operation), int spc)
+ dump_template_types (pretty_printer *buffer, tree types, int spc)
  {
    size_t i;
    size_t len = TREE_VEC_LENGTH (types);
      {
        tree elem = TREE_VEC_ELT (types, i);
        pp_underscore (buffer);
-       if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true))
+       if (!dump_generic_ada_node (buffer, elem, 0, spc, false, true))
        {
          pp_string (buffer, "unknown");
          pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
  }
  
  /* Dump in BUFFER the contents of all class instantiations associated with
-    a given template T.  CPP_CHECK is used to perform C++ queries on nodes.
-    SPC is the indentation level. */
+    a given template T.  SPC is the indentation level.  */
  
  static int
- dump_ada_template (pretty_printer *buffer, tree t,
-                  int (*cpp_check)(tree, cpp_operation), int spc)
+ dump_ada_template (pretty_printer *buffer, tree t, int spc)
  {
    /* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context.  */
    tree inst = DECL_VINDEX (t);
        INDENT (spc);
        pp_string (buffer, "package ");
        package_prefix = false;
-       dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
-       dump_template_types (buffer, types, cpp_check, spc);
+       dump_generic_ada_node (buffer, instance, t, spc, false, true);
+       dump_template_types (buffer, types, spc);
        pp_string (buffer, " is");
        spc += INDENT_INCR;
        newline_and_indent (buffer, spc);
  
        TREE_VISITED (get_underlying_decl (instance)) = 1;
        pp_string (buffer, "type ");
-       dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
+       dump_generic_ada_node (buffer, instance, t, spc, false, true);
        package_prefix = true;
  
        if (is_tagged_type (instance))
        else
        pp_string (buffer, " is limited ");
  
-       dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false);
+       dump_generic_ada_node (buffer, instance, t, spc, false, false);
        pp_newline (buffer);
        spc -= INDENT_INCR;
        newline_and_indent (buffer, spc);
        newline_and_indent (buffer, spc);
        pp_string (buffer, "use ");
        package_prefix = false;
-       dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
-       dump_template_types (buffer, types, cpp_check, spc);
+       dump_generic_ada_node (buffer, instance, t, spc, false, true);
+       dump_template_types (buffer, types, spc);
        package_prefix = true;
        pp_semicolon (buffer);
        pp_newline (buffer);
  static bool
  is_simple_enum (tree node)
  {
 -  unsigned HOST_WIDE_INT count = 0;
 +  HOST_WIDE_INT count = 0;
    tree value;
  
    for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
        if (TREE_CODE (int_val) != INTEGER_CST)
        int_val = DECL_INITIAL (int_val);
  
 -      if (!host_integerp (int_val, 0))
 +      if (!tree_fits_shwi_p (int_val))
        return false;
 -      else if (TREE_INT_CST_LOW (int_val) != count)
 +      else if (tree_to_shwi (int_val) != count)
        return false;
  
        count++;
@@@ -1805,14 -1828,12 +1814,12 @@@ static bool in_function = true
  static bool bitfield_used = false;
  
  /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
-    TYPE.  CPP_CHECK is used to perform C++ queries on nodes.  SPC is the
-    indentation level.  LIMITED_ACCESS indicates whether NODE can be referenced
-    via a "limited with" clause.  NAME_ONLY indicates whether we should only
-    dump the name of NODE, instead of its full declaration.  */
+    TYPE.  SPC is the indentation level.  LIMITED_ACCESS indicates whether NODE
+    can be referenced via a "limited with" clause.  NAME_ONLY indicates whether
+    we should only dump the name of NODE, instead of its full declaration.  */
  
  static int
- dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
-                      int (*cpp_check)(tree, cpp_operation), int spc,
+ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
                       int limited_access, bool name_only)
  {
    if (node == NULL_TREE)
  
      case TREE_BINFO:
        dump_generic_ada_node
-       (buffer, BINFO_TYPE (node), type, cpp_check,
-        spc, limited_access, name_only);
+       (buffer, BINFO_TYPE (node), type, spc, limited_access, name_only);
  
      case TREE_VEC:
        pp_string (buffer, "--- unexpected node: TREE_VEC");
      case ENUMERAL_TYPE:
        if (name_only)
        dump_generic_ada_node
-         (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
+         (buffer, TYPE_NAME (node), node, spc, 0, true);
        else
        {
          tree value = TYPE_VALUES (node);
              pp_string (buffer, "pragma Convention (C, ");
              dump_generic_ada_node
                (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
-                cpp_check, spc, 0, true);
+                spc, 0, true);
              pp_right_paren (buffer);
            }
          else
  
                  dump_generic_ada_node
                    (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
-                    cpp_check, spc, 0, true);
+                    spc, 0, true);
  
                  pp_string (buffer, " := ");
                  dump_generic_ada_node
                    (buffer,
                     TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
                       TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
-                    node, cpp_check, spc, false, true);
+                    node, spc, false, true);
                }
            }
        }
      case REFERENCE_TYPE:
        if (name_only && TYPE_NAME (node))
        dump_generic_ada_node
-         (buffer, TYPE_NAME (node), node, cpp_check,
-          spc, limited_access, true);
+         (buffer, TYPE_NAME (node), node, spc, limited_access, true);
  
        else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
        {
            {
              pp_string (buffer, " return ");
              dump_generic_ada_node
-               (buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true);
+               (buffer, TREE_TYPE (fnode), type, spc, 0, true);
            }
  
            /* If we are dumping the full type, it means we are part of a
                newline_and_indent (buffer, spc);
                pp_string (buffer, "pragma Convention (C, ");
                dump_generic_ada_node
-                 (buffer, type, 0, cpp_check, spc, false, true);
+                 (buffer, type, 0, spc, false, true);
                pp_right_paren (buffer);
              }
        }
                      && type_name != NULL_TREE)
                    dump_generic_ada_node
                      (buffer, type_name,
-                      TREE_TYPE (node), cpp_check, spc, is_access, true);
+                      TREE_TYPE (node), spc, is_access, true);
                  else
                    dump_generic_ada_node
                      (buffer, TREE_TYPE (node), TREE_TYPE (node),
-                      cpp_check, spc, 0, true);
+                      spc, 0, true);
                }
            }
        }
      case ARRAY_TYPE:
        if (name_only)
        dump_generic_ada_node
-         (buffer, TYPE_NAME (node), node, cpp_check,
-          spc, limited_access, true);
+         (buffer, TYPE_NAME (node), node, spc, limited_access, true);
        else
        dump_ada_array_type (buffer, node, spc);
        break;
        {
          if (TYPE_NAME (node))
            dump_generic_ada_node
-             (buffer, TYPE_NAME (node), node, cpp_check,
-              spc, limited_access, true);
+             (buffer, TYPE_NAME (node), node, spc, limited_access, true);
          else
            {
              pp_string (buffer, "anon_");
            }
        }
        else
-       print_ada_struct_decl
-         (buffer, node, type, cpp_check, spc, true);
+       print_ada_struct_decl (buffer, node, type, spc, true);
        break;
  
      case INTEGER_CST:
         to generate the (0 .. -1) range for flexible array members.  */
        if (TREE_TYPE (node) == sizetype)
        node = fold_convert (ssizetype, node);
 -      if (host_integerp (node, 0))
 -      pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
 -      else if (host_integerp (node, 1))
 -      pp_unsigned_wide_integer (buffer, TREE_INT_CST_LOW (node));
 +      if (tree_fits_shwi_p (node))
 +      pp_wide_integer (buffer, tree_to_shwi (node));
 +      else if (tree_fits_uhwi_p (node))
 +      pp_unsigned_wide_integer (buffer, tree_to_uhwi (node));
        else
        {
 -        tree val = node;
 -        unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (val);
 -        HOST_WIDE_INT high = TREE_INT_CST_HIGH (val);
 -
 -        if (tree_int_cst_sgn (val) < 0)
 +        wide_int val = node;
 +        int i;
 +        if (wi::neg_p (val))
            {
              pp_minus (buffer);
 -            high = ~high + !low;
 -            low = -low;
 +            val = -val;
            }
          sprintf (pp_buffer (buffer)->digit_buffer,
 -                 ADA_HOST_WIDE_INT_PRINT_DOUBLE_HEX,
 -                 (unsigned HOST_WIDE_INT) high, low);
 +                 "16#%" HOST_LONG_FORMAT "x", val.elt (val.get_len () - 1)); 
 +        for (i = val.get_len () - 2; i <= 0; i--)
 +          sprintf (pp_buffer (buffer)->digit_buffer,
 +                   HOST_WIDE_INT_PRINT_PADDED_HEX, val.elt (i));
          pp_string (buffer, pp_buffer (buffer)->digit_buffer);
        }
        break;
  
              pp_string (buffer, first ? "tagged limited " : " with ");
            }
-         else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
-                  && TYPE_METHODS (TREE_TYPE (node)))
+         else if (has_nontrivial_methods (TREE_TYPE (node)))
            pp_string (buffer, "limited ");
  
          dump_generic_ada_node
-           (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false);
+           (buffer, TREE_TYPE (node), type, spc, false, false);
        }
        break;
  
    return 1;
  }
  
- /* Dump in BUFFER NODE's methods.  CPP_CHECK is used to perform C++ queries on
-    nodes.  SPC is the indentation level.  */
+ /* Dump in BUFFER NODE's methods.  SPC is the indentation level.  Return 1 if
+    methods were printed, 0 otherwise.  */
  
- static void
- print_ada_methods (pretty_printer *buffer, tree node,
-                  int (*cpp_check)(tree, cpp_operation), int spc)
+ static int
+ print_ada_methods (pretty_printer *buffer, tree node, int spc)
  {
-   tree tmp = TYPE_METHODS (node);
    int res = 1;
+   tree tmp;
  
-   if (tmp)
-     {
-       pp_semicolon (buffer);
+   if (!has_nontrivial_methods (node))
+     return 0;
  
-       for (; tmp; tmp = TREE_CHAIN (tmp))
+   pp_semicolon (buffer);
+   for (tmp = TYPE_METHODS (node); tmp; tmp = TREE_CHAIN (tmp))
+     {
+       if (res)
        {
-         if (res)
-           {
-             pp_newline (buffer);
-             pp_newline (buffer);
-           }
-         res = print_ada_declaration (buffer, tmp, node, cpp_check, spc);
+         pp_newline (buffer);
+         pp_newline (buffer);
        }
+       res = print_ada_declaration (buffer, tmp, node, spc);
      }
+   return 1;
  }
  
  /* Dump in BUFFER anonymous types nested inside T's definition.
     PARENT is the parent node of T.
     FORWARD indicates whether a forward declaration of T should be generated.
-    CPP_CHECK is used to perform C++ queries on
-    nodes.  SPC is the indentation level.  */
+    SPC is the indentation level.  */
  
  static void
  dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
-                  int (*cpp_check)(tree, cpp_operation), int spc)
+                  int spc)
  {
    tree field, outer, decl;
  
    if (forward)
      {
        pp_string (buffer, "type ");
-       dump_generic_ada_node
-       (buffer, t, t, cpp_check, spc, false, true);
+       dump_generic_ada_node (buffer, t, t, spc, false, true);
        pp_semicolon (buffer);
        newline_and_indent (buffer, spc);
        TREE_VISITED (t) = 1;
                    /* Generate forward declaration.  */
  
                    pp_string (buffer, "type ");
-                   dump_generic_ada_node
-                     (buffer, decl, 0, cpp_check, spc, false, true);
+                   dump_generic_ada_node (buffer, decl, 0, spc, false, true);
                    pp_semicolon (buffer);
                    newline_and_indent (buffer, spc);
  
  
              case UNION_TYPE:
                TREE_VISITED (t) = 1;
-               dump_nested_types (buffer, field, t, false, cpp_check, spc);
+               dump_nested_types (buffer, field, t, false, spc);
  
                pp_string (buffer, "type ");
  
                if (TYPE_NAME (TREE_TYPE (field)))
                  {
                    dump_generic_ada_node
-                     (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check,
-                      spc, false, true);
+                     (buffer, TYPE_NAME (TREE_TYPE (field)), 0, spc, false,
+                      true);
                    pp_string (buffer, " (discr : unsigned := 0) is ");
                    print_ada_struct_decl
-                     (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+                     (buffer, TREE_TYPE (field), t, spc, false);
  
                    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
                    dump_generic_ada_node
-                     (buffer, TREE_TYPE (field), 0, cpp_check,
-                      spc, false, true);
+                     (buffer, TREE_TYPE (field), 0, spc, false, true);
                    pp_string (buffer, ");");
                    newline_and_indent (buffer, spc);
  
                    pp_string (buffer, "pragma Unchecked_Union (");
                    dump_generic_ada_node
-                     (buffer, TREE_TYPE (field), 0, cpp_check,
-                      spc, false, true);
+                     (buffer, TREE_TYPE (field), 0, spc, false, true);
                    pp_string (buffer, ");");
                  }
                else
                      (buffer, parent, field,
                        "_union (discr : unsigned := 0) is ");
                    print_ada_struct_decl
-                     (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+                     (buffer, TREE_TYPE (field), t, spc, false);
                    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
                    dump_ada_double_name (buffer, parent, field, "_union);");
                    newline_and_indent (buffer, spc);
                  {
                    pp_string (buffer, "type ");
                    dump_generic_ada_node
-                     (buffer, t, parent, 0, spc, false, true);
+                     (buffer, t, parent, spc, false, true);
                    pp_semicolon (buffer);
                    newline_and_indent (buffer, spc);
                  }
  
                TREE_VISITED (t) = 1;
-               dump_nested_types (buffer, field, t, false, cpp_check, spc);
+               dump_nested_types (buffer, field, t, false, spc);
                pp_string (buffer, "type ");
  
                if (TYPE_NAME (TREE_TYPE (field)))
                  {
                    dump_generic_ada_node
-                     (buffer, TREE_TYPE (field), 0, cpp_check,
-                      spc, false, true);
+                     (buffer, TREE_TYPE (field), 0, spc, false, true);
                    pp_string (buffer, " is ");
                    print_ada_struct_decl
-                     (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+                     (buffer, TREE_TYPE (field), t, spc, false);
                    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
                    dump_generic_ada_node
-                     (buffer, TREE_TYPE (field), 0, cpp_check,
-                      spc, false, true);
+                     (buffer, TREE_TYPE (field), 0, spc, false, true);
                    pp_string (buffer, ");");
                  }
                else
                    dump_ada_double_name
                      (buffer, parent, field, "_struct is ");
                    print_ada_struct_decl
-                     (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+                     (buffer, TREE_TYPE (field), t, spc, false);
                    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
                    dump_ada_double_name (buffer, parent, field, "_struct);");
                  }
@@@ -2542,12 -2552,11 +2537,11 @@@ type_name (tree t
  }
  
  /* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
-    CPP_CHECK is used to perform C++ queries on nodes.  SPC is the indentation
-    level.  Return 1 if a declaration was printed, 0 otherwise.  */
+    SPC is the indentation level.  Return 1 if a declaration was printed,
+    0 otherwise.  */
  
  static int
- print_ada_declaration (pretty_printer *buffer, tree t, tree type,
-                      int (*cpp_check)(tree, cpp_operation), int spc)
+ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
  {
    int is_var = 0, need_indent = 0;
    int is_class = false;
    tree orig = NULL_TREE;
  
    if (cpp_check && cpp_check (t, IS_TEMPLATE))
-     return dump_ada_template (buffer, t, cpp_check, spc);
+     return dump_ada_template (buffer, t, spc);
  
    if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
      /* Skip enumeral values: will be handled as part of the type itself.  */
              if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
                {
                  pp_string (buffer, "--  skipped empty struct ");
-                 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+                 dump_generic_ada_node (buffer, t, type, spc, false, true);
                }
              else
                {
                  if (!TREE_VISITED (stub)
                      && DECL_SOURCE_FILE (stub) == source_file_base)
-                   dump_nested_types
-                     (buffer, stub, stub, true, cpp_check, spc);
+                   dump_nested_types (buffer, stub, stub, true, spc);
  
                  pp_string (buffer, "subtype ");
-                 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+                 dump_generic_ada_node (buffer, t, type, spc, false, true);
                  pp_string (buffer, " is ");
-                 dump_generic_ada_node
-                   (buffer, typ, type, 0, spc, false, true);
+                 dump_generic_ada_node (buffer, typ, type, spc, false, true);
                  pp_semicolon (buffer);
                }
              return 1;
            if (!TYPE_FIELDS (TREE_TYPE (t)))
              {
                pp_string (buffer, "--  skipped empty struct ");
-               dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+               dump_generic_ada_node (buffer, t, type, spc, false, true);
                return 1;
              }
  
                    || *IDENTIFIER_POINTER (decl_name) == '$'))
              {
                pp_string (buffer, "--  skipped anonymous struct ");
-               dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+               dump_generic_ada_node (buffer, t, type, spc, false, true);
                TREE_VISITED (t) = 1;
                return 1;
              }
              pp_string (buffer, "subtype ");
            else
              {
-               dump_nested_types (buffer, t, t, false, cpp_check, spc);
+               dump_nested_types (buffer, t, t, false, spc);
  
                  if (separate_class_package (t))
                  {
                    is_class = true;
                    pp_string (buffer, "package Class_");
-                   dump_generic_ada_node
-                     (buffer, t, type, 0, spc, false, true);
+                   dump_generic_ada_node (buffer, t, type, spc, false, true);
                    pp_string (buffer, " is");
                    spc += INDENT_INCR;
                    newline_and_indent (buffer, spc);
  
          case FUNCTION_TYPE:
            pp_string (buffer, "--  skipped function type ");
-           dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+           dump_generic_ada_node (buffer, t, type, spc, false, true);
            return 1;
            break;
  
        INDENT (spc);
  
        /* Print variable's name.  */
-       dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true);
+       dump_generic_ada_node (buffer, t, type, spc, false, true);
  
        if (TREE_CODE (t) == TYPE_DECL)
        {
  
          if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
            dump_generic_ada_node
-             (buffer, TYPE_NAME (orig), type,
-              cpp_check, spc, false, true);
+             (buffer, TYPE_NAME (orig), type, spc, false, true);
          else
            dump_ada_array_type (buffer, t, spc);
        }
                  && TREE_CODE (tmp) != INTEGER_TYPE)
                pp_string (buffer, "aliased ");
  
-             dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true);
+             dump_generic_ada_node (buffer, tmp, type, spc, false, true);
            }
          else
            {
      }
    else if (TREE_CODE (t) == FUNCTION_DECL)
      {
-       bool is_function = true, is_method, is_abstract_class = false;
+       bool is_function = true, is_abstract_class = false;
+       bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
        tree decl_name = DECL_NAME (t);
        int prev_in_function = in_function;
        bool is_abstract = false;
        pp_string (buffer, "function ");
  
        in_function = is_function;
-       is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
  
        if (is_destructor)
        print_destructor (buffer, t);
          else
            {
              dump_generic_ada_node
-               (buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check,
-                spc, false, true);
+               (buffer, TREE_TYPE (TREE_TYPE (t)), type, spc, false, true);
            }
        }
  
-       if (is_constructor && cpp_check && type
-         && AGGREGATE_TYPE_P (type)
+       if (is_constructor
+         && RECORD_OR_UNION_TYPE_P (type)
          && TYPE_METHODS (type))
        {
-         tree tmp = TYPE_METHODS (type);
+         tree tmp;
  
-         for (; tmp; tmp = TREE_CHAIN (tmp))
+         for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
            if (cpp_check (tmp, IS_ABSTRACT))
              {
                is_abstract_class = 1;
        INDENT (spc);
  
        /* Anonymous structs/unions */
-       dump_generic_ada_node
-       (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
+       dump_generic_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
  
        if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
          || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
        pp_string (buffer, " is ");
  
        /* Check whether we have an Ada interface compatible class.  */
-       if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t))
+       if (cpp_check
+         && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
          && TYPE_METHODS (TREE_TYPE (t)))
        {
          int num_fields = 0;
-         tree tmp = TYPE_FIELDS (TREE_TYPE (t));
+         tree tmp;
  
          /* Check that there are no fields other than the virtual table.  */
-         for (; tmp; tmp = TREE_CHAIN (tmp))
+         for (tmp = TYPE_FIELDS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
            {
              if (TREE_CODE (tmp) == TYPE_DECL)
                continue;
          newline_and_indent (buffer, spc);
          pp_string (buffer, "pragma Import (CPP, ");
          dump_generic_ada_node
-           (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check,
-            spc, false, true);
+           (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false, true);
          pp_right_paren (buffer);
  
-         print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc);
+         print_ada_methods (buffer, TREE_TYPE (t), spc);
        }
        else
        {
          if (is_abstract_record)
            pp_string (buffer, "abstract ");
-         dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false);
+         dump_generic_ada_node (buffer, t, t, spc, false, false);
        }
      }
    else
        check_name (buffer, t);
  
        /* Print variable/type's name.  */
-       dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true);
+       dump_generic_ada_node (buffer, t, t, spc, false, true);
  
        if (TREE_CODE (t) == TYPE_DECL)
        {
  
          pp_string (buffer, " is ");
  
-         dump_generic_ada_node
-           (buffer, orig, t, cpp_check, spc, false, is_subtype);
+         dump_generic_ada_node (buffer, orig, t, spc, false, is_subtype);
        }
        else
        {
                pp_string (buffer, "aliased ");
  
              dump_generic_ada_node
-               (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
+               (buffer, TREE_TYPE (t), t, spc, false, true);
            }
          else
            {
                pp_string (buffer, "aliased ");
  
              dump_generic_ada_node
-               (buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check,
-                spc, false, true);
+               (buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false, true);
            }
        }
      }
        pp_string (buffer, "end;");
        newline_and_indent (buffer, spc);
        pp_string (buffer, "use Class_");
-       dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+       dump_generic_ada_node (buffer, t, type, spc, false, true);
        pp_semicolon (buffer);
        pp_newline (buffer);
  
  }
  
  /* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
-    with Ada syntax.  CPP_CHECK is used to perform C++ queries on nodes.  SPC
-    is the indentation level.  If DISPLAY_CONVENTION is true, also print the
-    pragma Convention for NODE.  */
+    with Ada syntax.  SPC is the indentation level.  If DISPLAY_CONVENTION is
+    true, also print the pragma Convention for NODE.  */
  
  static void
- print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
-                      int (*cpp_check)(tree, cpp_operation), int spc,
+ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc,
                       bool display_convention)
  {
    tree tmp;
-   int is_union =
-     TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
+   const bool is_union
+     TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
    char buf[32];
    int field_num = 0;
    int field_spc = spc + INDENT_INCR;
              if (!is_tagged_type (TREE_TYPE (tmp)))
                {
                  if (!TYPE_NAME (TREE_TYPE (tmp)))
-                   print_ada_declaration
-                     (buffer, tmp, type, cpp_check, field_spc);
+                   print_ada_declaration (buffer, tmp, type, field_spc);
                  else
                    {
                      INDENT (field_spc);
                      pp_newline (buffer);
                    }
  
-                 if (print_ada_declaration (buffer,
-                                            tmp, type, cpp_check, field_spc))
+                 if (print_ada_declaration (buffer, tmp, type, field_spc))
                    {
                      pp_newline (buffer);
                      field_num++;
  
    if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
      {
-       if (TYPE_METHODS (TREE_TYPE (type)))
+       if (has_nontrivial_methods (TREE_TYPE (type)))
        pp_string (buffer, "pragma Import (CPP, ");
        else
        pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
      pp_string (buffer, "pragma Convention (C, ");
  
    package_prefix = false;
-   dump_generic_ada_node
-     (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+   dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
    package_prefix = true;
    pp_right_paren (buffer);
  
        newline_and_indent (buffer, spc);
        pp_string (buffer, "pragma Unchecked_Union (");
  
-       dump_generic_ada_node
-       (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+       dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
        pp_right_paren (buffer);
      }
  
        newline_and_indent (buffer, spc);
        pp_string (buffer, "pragma Pack (");
        dump_generic_ada_node
-       (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+       (buffer, TREE_TYPE (type), type, spc, false, true);
        pp_right_paren (buffer);
        bitfield_used = false;
      }
  
-   print_ada_methods (buffer, node, cpp_check, spc);
+   need_semicolon = !print_ada_methods (buffer, node, spc);
  
    /* Print the static fields of the structure, if any.  */
-   need_semicolon = TYPE_METHODS (node) == NULL_TREE;
    for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
      {
        if (DECL_NAME (tmp) && TREE_STATIC (tmp))
            }
          pp_newline (buffer);
          pp_newline (buffer);
-         print_ada_declaration (buffer, tmp, type, cpp_check, spc);
+         print_ada_declaration (buffer, tmp, type, spc);
        }
      }
  }
  
  /* Dump all the declarations in SOURCE_FILE to an Ada spec.
     COLLECT_ALL_REFS is a front-end callback used to collect all relevant
-    nodes for SOURCE_FILE.  CPP_CHECK is used to perform C++ queries on
-    nodes.  */
+    nodes for SOURCE_FILE.  CHECK is used to perform C++ queries on nodes.  */
  
  static void
  dump_ads (const char *source_file,
          void (*collect_all_refs)(const char *),
-         int (*cpp_check)(tree, cpp_operation))
+         int (*check)(const_tree, cpp_operation))
  {
    char *ads_name;
    char *pkg_name;
        (*collect_all_refs) (source_file);
  
        /* Dump all references.  */
-       dump_ada_nodes (&pp, source_file, cpp_check);
+       cpp_check = check;
+       dump_ada_nodes (&pp, source_file);
  
        /* Requires Ada 2005 syntax, so generate corresponding pragma.
           Also, disable style checks since this file is auto-generated.  */
@@@ -3355,21 -3349,21 +3334,21 @@@ collect_source_ref (const char *filenam
  }
  
  /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
-    using callbacks COLLECT_ALL_REFS and CPP_CHECK.
+    using callbacks COLLECT_ALL_REFS and CHECK.
     COLLECT_ALL_REFS is a front-end callback used to collect all relevant
     nodes for a given source file.
-    CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C
+    CHECK is used to perform C++ queries on nodes, or NULL for the C
     front-end.  */
  
  void
  dump_ada_specs (void (*collect_all_refs)(const char *),
-               int (*cpp_check)(tree, cpp_operation))
+               int (*check)(const_tree, cpp_operation))
  {
    int i;
  
    /* Iterate over the list of files to dump specs for */
    for (i = 0; i < source_refs_used; i++)
-     dump_ads (source_refs[i], collect_all_refs, cpp_check);
+     dump_ads (source_refs[i], collect_all_refs, check);
  
    /* Free files table.  */
    free (source_refs);
diff --combined gcc/c-family/c-common.c
index 6f6eeea473282c99bdb1d16cf958147b0237c3dd,030ee5a643d365cb3fb4a9be76f81122e132a0a9..3496d3cdb128ea95b0700aa754dfde3db36a10d7
@@@ -39,11 -39,9 +39,10 @@@ along with GCC; see the file COPYING3
  #include "diagnostic.h"
  #include "tree-iterator.h"
  #include "hashtab.h"
- #include "tree-mudflap.h"
  #include "opts.h"
  #include "cgraph.h"
  #include "target-def.h"
 +#include "wide-int-print.h"
  
  cpp_reader *parse_in;         /* Declared in c-pragma.h.  */
  
@@@ -377,6 -375,8 +376,8 @@@ static tree handle_omp_declare_simd_att
                                               bool *);
  static tree handle_omp_declare_target_attribute (tree *, tree, tree, int,
                                                 bool *);
+ static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *);
+ static tree handle_bnd_legacy (tree *, tree, tree, int, bool *);
  
  static void check_function_nonnull (tree, int, tree *);
  static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@@ -411,6 -411,8 +412,8 @@@ const struct c_common_resword c_common_
    { "_Alignof",               RID_ALIGNOF,   D_CONLY },
    { "_Bool",          RID_BOOL,      D_CONLY },
    { "_Complex",               RID_COMPLEX,    0 },
+   { "_Cilk_spawn",      RID_CILK_SPAWN, 0 },
+   { "_Cilk_sync",       RID_CILK_SYNC,  0 },
    { "_Imaginary",     RID_IMAGINARY, D_CONLY },
    { "_Decimal32",       RID_DFLOAT32,  D_CONLY | D_EXT },
    { "_Decimal64",       RID_DFLOAT64,  D_CONLY | D_EXT },
@@@ -759,6 -761,10 +762,10 @@@ const struct attribute_spec c_common_at
                              handle_omp_declare_simd_attribute, false },
    { "omp declare target",     0, 0, true, false, false,
                              handle_omp_declare_target_attribute, false },
+   { "bnd_variable_size",      0, 0, true,  false, false,
+                             handle_bnd_variable_size_attribute, false },
+   { "bnd_legacy",             0, 0, true, false, false,
+                             handle_bnd_legacy, false },
    { NULL,                     0, 0, false, false, false, NULL, false }
  };
  
@@@ -849,7 -855,7 +856,7 @@@ finish_fname_decls (void
        for (saved = TREE_PURPOSE (stack); saved; saved = TREE_CHAIN (saved))
        {
          tree decl = TREE_PURPOSE (saved);
 -        unsigned ix = TREE_INT_CST_LOW (TREE_VALUE (saved));
 +        unsigned ix = tree_to_hwi (TREE_VALUE (saved));
  
          *fname_vars[ix].decl = decl;
        }
@@@ -4088,12 -4094,9 +4095,12 @@@ shorten_compare (tree *op0_ptr, tree *o
        {
          /* Convert primop1 to target type, but do not introduce
             additional overflow.  We know primop1 is an int_cst.  */
 -        primop1 = force_fit_type_double (*restype_ptr,
 -                                         tree_to_double_int (primop1),
 -                                         0, TREE_OVERFLOW (primop1));
 +        primop1 = force_fit_type (*restype_ptr,
 +                                  wide_int::from
 +                                    (primop1,
 +                                     TYPE_PRECISION (*restype_ptr),
 +                                     TYPE_SIGN (TREE_TYPE (primop1))),
 +                                  0, TREE_OVERFLOW (primop1));
        }
        if (type != *restype_ptr)
        {
          maxval = convert (*restype_ptr, maxval);
        }
  
 -      if (unsignedp && unsignedp0)
 -      {
 -        min_gt = INT_CST_LT_UNSIGNED (primop1, minval);
 -        max_gt = INT_CST_LT_UNSIGNED (primop1, maxval);
 -        min_lt = INT_CST_LT_UNSIGNED (minval, primop1);
 -        max_lt = INT_CST_LT_UNSIGNED (maxval, primop1);
 -      }
 -      else
 -      {
 -        min_gt = INT_CST_LT (primop1, minval);
 -        max_gt = INT_CST_LT (primop1, maxval);
 -        min_lt = INT_CST_LT (minval, primop1);
 -        max_lt = INT_CST_LT (maxval, primop1);
 -      }
 +      min_gt = INT_CST_LT (primop1, minval);
 +      max_gt = INT_CST_LT (primop1, maxval);
 +      min_lt = INT_CST_LT (minval, primop1);
 +      max_lt = INT_CST_LT (maxval, primop1);
  
        val = 0;
        /* This used to be a switch, but Genix compiler can't handle that.  */
@@@ -4395,7 -4408,8 +4402,7 @@@ pointer_int_sum (location_t loc, enum t
                              convert (TREE_TYPE (intop), size_exp), 1);
      intop = convert (sizetype, t);
      if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
 -      intop = build_int_cst_wide (TREE_TYPE (intop), TREE_INT_CST_LOW (intop),
 -                                TREE_INT_CST_HIGH (intop));
 +      intop = wide_int_to_tree (TREE_TYPE (intop), intop);
    }
  
    /* Create the sum or difference.  */
@@@ -4768,7 -4782,7 +4775,7 @@@ c_type_hash (const void *p
    if (TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
      size = 0;
    else
 -    size = TREE_INT_CST_LOW (TYPE_SIZE (t));
 +    size = tree_to_hwi (TYPE_SIZE (t));
    return ((size << 24) | (n_elements << shift));
  }
  
@@@ -5214,8 -5228,8 +5221,8 @@@ c_define_builtins (tree va_list_ref_typ
  
    build_common_builtin_nodes ();
  
-   if (flag_mudflap)
-     mudflap_init ();
+   if (flag_enable_cilkplus)
+     cilk_init_builtins ();
  }
  
  /* Like get_identifier, but avoid warnings about null arguments when
@@@ -5453,7 -5467,7 +5460,7 @@@ c_common_nodes_and_builtins (void
    }
  
    /* This node must not be shared.  */
 -  void_zero_node = make_node (INTEGER_CST);
 +  void_zero_node = make_int_cst (1, 1);
    TREE_TYPE (void_zero_node) = void_type_node;
  
    void_list_node = build_void_list_node ();
  
    /* Create the built-in __null node.  It is important that this is
       not shared.  */
 -  null_node = make_node (INTEGER_CST);
 +  null_node = make_int_cst (1, 1);
    TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
  
    /* Since builtin_types isn't gc'ed, don't export these nodes.  */
@@@ -6042,12 -6056,22 +6049,12 @@@ c_add_case_label (location_t loc, splay
  static void
  match_case_to_enum_1 (tree key, tree type, tree label)
  {
 -  char buf[2 + 2*HOST_BITS_PER_WIDE_INT/4 + 1];
 -
 -  /* ??? Not working too hard to print the double-word value.
 -     Should perhaps be done with %lwd in the diagnostic routines?  */
 -  if (TREE_INT_CST_HIGH (key) == 0)
 -    snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED,
 -            TREE_INT_CST_LOW (key));
 -  else if (!TYPE_UNSIGNED (type)
 -         && TREE_INT_CST_HIGH (key) == -1
 -         && TREE_INT_CST_LOW (key) != 0)
 -    snprintf (buf, sizeof (buf), "-" HOST_WIDE_INT_PRINT_UNSIGNED,
 -            -TREE_INT_CST_LOW (key));
 +  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
 +
 +  if (tree_fits_hwi_p (key, TYPE_SIGN (type)))
 +    print_dec (key, buf, TYPE_SIGN (type));
    else
 -    snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_DOUBLE_HEX,
 -            (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (key),
 -            (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (key));
 +    print_hex (key, buf);
  
    if (TYPE_NAME (type) == 0)
      warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
@@@ -6970,11 -6994,11 +6977,11 @@@ get_priority (tree args, bool is_destru
  
    arg = TREE_VALUE (args);
    arg = default_conversion (arg);
 -  if (!host_integerp (arg, /*pos=*/0)
 +  if (!tree_fits_shwi_p (arg)
        || !INTEGRAL_TYPE_P (TREE_TYPE (arg)))
      goto invalid;
  
 -  pri = tree_low_cst (arg, /*pos=*/0);
 +  pri = tree_to_shwi (arg);
    if (pri < 0 || pri > MAX_INIT_PRIORITY)
      goto invalid;
  
@@@ -7971,11 -7995,11 +7978,11 @@@ handle_alloc_size_attribute (tree *node
    for (; args; args = TREE_CHAIN (args))
      {
        tree position = TREE_VALUE (args);
 +      wide_int p;
  
        if (TREE_CODE (position) != INTEGER_CST
 -        || TREE_INT_CST_HIGH (position)
 -        || TREE_INT_CST_LOW (position) < 1
 -        || TREE_INT_CST_LOW (position) > arg_count )
 +        || wi::ltu_p (p = wide_int (position), 1)
 +        || wi::gtu_p (p, arg_count))
        {
          warning (OPT_Wattributes,
                   "alloc_size parameter outside range");
@@@ -8000,6 -8024,38 +8007,38 @@@ handle_fnspec_attribute (tree *node ATT
    return NULL_TREE;
  }
  
+ /* Handle a "bnd_variable_size" attribute; arguments as in
+    struct attribute_spec.handler.  */
+ static tree
+ handle_bnd_variable_size_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+                                   int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+   if (TREE_CODE (*node) != FIELD_DECL)
+     {
+       warning (OPT_Wattributes, "%qE attribute ignored", name);
+       *no_add_attrs = true;
+     }
+   return NULL_TREE;
+ }
+ /* Handle a "bnd_legacy" attribute; arguments as in
+    struct attribute_spec.handler.  */
+ static tree
+ handle_bnd_legacy (tree *node, tree name, tree ARG_UNUSED (args),
+                  int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+   if (TREE_CODE (*node) != FUNCTION_DECL)
+     {
+       warning (OPT_Wattributes, "%qE attribute ignored", name);
+       *no_add_attrs = true;
+     }
+   return NULL_TREE;
+ }
  /* Handle a "warn_unused" attribute; arguments as in
     struct attribute_spec.handler.  */
  
@@@ -8416,14 -8472,14 +8455,14 @@@ handle_vector_size_attribute (tree *nod
  
    size = TREE_VALUE (args);
  
 -  if (!host_integerp (size, 1))
 +  if (!tree_fits_uhwi_p (size))
      {
        warning (OPT_Wattributes, "%qE attribute ignored", name);
        return NULL_TREE;
      }
  
    /* Get the vector size (in bytes).  */
 -  vecsize = tree_low_cst (size, 1);
 +  vecsize = tree_to_uhwi (size);
  
    /* We need to provide for vector pointers, vector arrays, and
       functions returning vectors.  For example:
        || (!SCALAR_FLOAT_MODE_P (orig_mode)
          && GET_MODE_CLASS (orig_mode) != MODE_INT
          && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
 -      || !host_integerp (TYPE_SIZE_UNIT (type), 1)
 +      || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
        || TREE_CODE (type) == BOOLEAN_TYPE)
      {
        error ("invalid vector type for attribute %qE", name);
        return NULL_TREE;
      }
  
 -  if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1))
 +  if (vecsize % tree_to_uhwi (TYPE_SIZE_UNIT (type)))
      {
        error ("vector size not an integral multiple of component size");
        return NULL;
      }
  
    /* Calculate how many units fit in the vector.  */
 -  nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
 +  nunits = vecsize / tree_to_uhwi (TYPE_SIZE_UNIT (type));
    if (nunits & (nunits - 1))
      {
        error ("number of components of the vector not a power of two");
@@@ -8631,7 -8687,7 +8670,7 @@@ check_function_sentinel (const_tree fnt
        if (TREE_VALUE (attr))
        {
          tree p = TREE_VALUE (TREE_VALUE (attr));
 -        pos = TREE_INT_CST_LOW (p);
 +        pos = tree_to_hwi (p);
        }
  
        /* The sentinel must be one of the varargs, i.e.
@@@ -8704,14 -8760,13 +8743,14 @@@ check_nonnull_arg (void * ARG_UNUSED (c
  static bool
  get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
  {
 -  /* Verify the arg number is a constant.  */
 -  if (TREE_CODE (arg_num_expr) != INTEGER_CST
 -      || TREE_INT_CST_HIGH (arg_num_expr) != 0)
 +  /* Verify the arg number is a small constant.  */
 +  if (cst_fits_uhwi_p (arg_num_expr))
 +    {
 +      *valp = tree_to_hwi (arg_num_expr);
 +      return true;
 +    }
 +  else
      return false;
 -
 -  *valp = TREE_INT_CST_LOW (arg_num_expr);
 -  return true;
  }
  
  /* Handle a "nothrow" attribute; arguments as in
@@@ -8909,7 -8964,7 +8948,7 @@@ parse_optimize_options (tree args, boo
        if (TREE_CODE (value) == INTEGER_CST)
        {
          char buffer[20];
 -        sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
 +        sprintf (buffer, "-O%ld", (long) tree_to_hwi (value));
          vec_safe_push (optimize_args, ggc_strdup (buffer));
        }
  
@@@ -9148,10 -9203,11 +9187,10 @@@ check_function_arguments_recurse (void 
            /* Extract the argument number, which was previously checked
               to be valid.  */
            format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
 +          
 +          gcc_assert (tree_fits_uhwi_p (format_num_expr));
  
 -          gcc_assert (TREE_CODE (format_num_expr) == INTEGER_CST
 -                      && !TREE_INT_CST_HIGH (format_num_expr));
 -
 -          format_num = TREE_INT_CST_LOW (format_num_expr);
 +          format_num = tree_to_uhwi (format_num_expr);
  
            for (inner_arg = first_call_expr_arg (param, &iter), i = 1;
                 inner_arg != 0;
@@@ -9405,7 -9461,7 +9444,7 @@@ c_parse_error (const char *gmsgid, enu
           || token_type == CPP_CHAR16
           || token_type == CPP_CHAR32)
      {
 -      unsigned int val = TREE_INT_CST_LOW (value);
 +      unsigned int val = tree_to_hwi (value);
        const char *prefix;
  
        switch (token_type)
@@@ -9659,7 -9715,8 +9698,7 @@@ fold_offsetof_1 (tree expr
          return error_mark_node;
        }
        off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
 -                          size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t),
 -                                                  1)
 +                          size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
                                      / BITS_PER_UNIT));
        break;
  
@@@ -9877,6 -9934,11 +9916,11 @@@ invalid_indirection_error (location_t l
                "invalid type argument of %<->%> (have %qT)",
                type);
        break;
+     case RO_ARROW_STAR:
+       error_at (loc,
+               "invalid type argument of %<->*%> (have %qT)",
+               type);
+       break;
      case RO_IMPLICIT_CONVERSION:
        error_at (loc,
                "invalid type argument of implicit conversion (have %qT)",
@@@ -10023,7 -10085,7 +10067,7 @@@ complete_array_type (tree *ptype, tree 
      {
        error ("size of array is too large");
        /* If we proceed with the array type as it is, we'll eventually
 -       crash in tree_low_cst().  */
 +       crash in tree_to_uhwi().  */
        type = error_mark_node;
      }
  
@@@ -10081,7 -10143,7 +10125,7 @@@ sync_resolve_size (tree function, vec<t
    if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
      goto incompatible;
  
 -  size = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
 +  size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
    if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
      return size;
  
@@@ -10240,7 -10302,7 +10284,7 @@@ get_atomic_generic_size (location_t loc
        return 0;
      }
  
 -  size_0 = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type_0)), 1);
 +  size_0 = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type_0)));
  
    /* Zero size objects are not allowed.  */
    if (size_0 == 0)
                    function);
          return 0;
        }
 -      size = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
 +      size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
        if (size != size_0)
        {
          error_at (loc, "size mismatch in argument %d of %qE", x + 1,
        tree p = (*params)[x];
        if (TREE_CODE (p) == INTEGER_CST)
          {
 -        int i = tree_low_cst (p, 1);
 +        int i = tree_to_uhwi (p);
          if (i < 0 || (i & MEMMODEL_MASK) >= MEMMODEL_LAST)
            {
              warning_at (loc, OPT_Winvalid_memory_model,
@@@ -11153,24 -11215,24 +11197,24 @@@ warn_for_sign_compare (location_t locat
        if (TREE_CODE (op1) == BIT_NOT_EXPR)
        op1 = c_common_get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
  
 -      if (host_integerp (op0, 0) || host_integerp (op1, 0))
 +      if (tree_fits_shwi_p (op0) || tree_fits_shwi_p (op1))
          {
            tree primop;
            HOST_WIDE_INT constant, mask;
            int unsignedp;
            unsigned int bits;
  
 -          if (host_integerp (op0, 0))
 +          if (tree_fits_shwi_p (op0))
              {
                primop = op1;
                unsignedp = unsignedp1;
 -              constant = tree_low_cst (op0, 0);
 +              constant = tree_to_shwi (op0);
              }
            else
              {
                primop = op0;
                unsignedp = unsignedp0;
 -              constant = tree_low_cst (op1, 0);
 +              constant = tree_to_shwi (op1);
              }
  
            bits = TYPE_PRECISION (TREE_TYPE (primop));
@@@ -11610,8 -11672,8 +11654,8 @@@ convert_vector_to_pointer_for_subscrip
        tree type1;
  
        if (TREE_CODE (index) == INTEGER_CST)
 -        if (!host_integerp (index, 1)
 -            || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1)
 +        if (!tree_fits_uhwi_p (index)
 +            || ((unsigned HOST_WIDE_INT) tree_to_uhwi (index)
                 >= TYPE_VECTOR_SUBPARTS (type)))
            warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
  
index d03279283264f9620a75b069a199646367d5ceeb,09c75c4ff9b5b85157a4d865c395cb4e53016777..94f72eceb2e7d4dc194c7fc47b25c9fd89c16275
@@@ -106,7 -106,7 +106,7 @@@ static voi
  builtin_define_type_sizeof (const char *name, tree type)
  {
    builtin_define_with_int_value (name,
 -                               tree_low_cst (TYPE_SIZE_UNIT (type), 1));
 +                               tree_to_uhwi (TYPE_SIZE_UNIT (type)));
  }
  
  /* Define the float.h constants for TYPE using NAME_PREFIX, FP_SUFFIX,
@@@ -648,7 -648,7 +648,7 @@@ cpp_atomic_builtins (cpp_reader *pfile
    /* Tell the source code about various types.  These map to the C++11 and C11
       macros where 2 indicates lock-free always, and 1 indicates sometimes
       lock free.  */
 -#define SIZEOF_NODE(T) (tree_low_cst (TYPE_SIZE_UNIT (T), 1))
 +#define SIZEOF_NODE(T) (tree_to_uhwi (TYPE_SIZE_UNIT (T)))
  #define SWAP_INDEX(T) ((SIZEOF_NODE (T) < SWAP_LIMIT) ? SIZEOF_NODE (T) : 0)
    builtin_define_with_int_value ("__GCC_ATOMIC_BOOL_LOCK_FREE", 
                        (have_swap[SWAP_INDEX (boolean_type_node)]? 2 : 1));
                        (have_swap[psize]? 2 : 1));
  }
  
+ /* Return the value for __GCC_IEC_559.  */
+ static int
+ cpp_iec_559_value (void)
+ {
+   /* The default is support for IEEE 754-2008.  */
+   int ret = 2;
+   /* float and double must be binary32 and binary64.  If they are but
+      with reversed NaN convention, at most IEEE 754-1985 is
+      supported.  */
+   const struct real_format *ffmt
+     = REAL_MODE_FORMAT (TYPE_MODE (float_type_node));
+   const struct real_format *dfmt
+     = REAL_MODE_FORMAT (TYPE_MODE (double_type_node));
+   if (!ffmt->qnan_msb_set || !dfmt->qnan_msb_set)
+     ret = 1;
+   if (ffmt->b != 2
+       || ffmt->p != 24
+       || ffmt->pnan != 24
+       || ffmt->emin != -125
+       || ffmt->emax != 128
+       || ffmt->signbit_rw != 31
+       || ffmt->round_towards_zero
+       || !ffmt->has_sign_dependent_rounding
+       || !ffmt->has_nans
+       || !ffmt->has_inf
+       || !ffmt->has_denorm
+       || !ffmt->has_signed_zero
+       || dfmt->b != 2
+       || dfmt->p != 53
+       || dfmt->pnan != 53
+       || dfmt->emin != -1021
+       || dfmt->emax != 1024
+       || dfmt->signbit_rw != 63
+       || dfmt->round_towards_zero
+       || !dfmt->has_sign_dependent_rounding
+       || !dfmt->has_nans
+       || !dfmt->has_inf
+       || !dfmt->has_denorm
+       || !dfmt->has_signed_zero)
+     ret = 0;
+   /* In strict C standards conformance mode, consider unpredictable
+      excess precision to mean lack of IEEE 754 support.  ??? The same
+      should apply to unpredictable contraction, but at present
+      standards conformance options do not enable conforming
+      contraction.  For C++, and outside strict conformance mode, do
+      not consider these options to mean lack of IEEE 754 support.  */
+   if (flag_iso
+       && !c_dialect_cxx ()
+       && TARGET_FLT_EVAL_METHOD != 0
+       && flag_excess_precision != EXCESS_PRECISION_STANDARD)
+     ret = 0;
+   /* Various options are contrary to IEEE 754 semantics.  */
+   if (flag_unsafe_math_optimizations
+       || flag_associative_math
+       || flag_reciprocal_math
+       || flag_finite_math_only
+       || !flag_signed_zeros
+       || flag_single_precision_constant)
+     ret = 0;
+   /* If the target does not support IEEE 754 exceptions and rounding
+      modes, consider IEEE 754 support to be absent.  */
+   if (!targetm.float_exceptions_rounding_supported_p ())
+     ret = 0;
+   return ret;
+ }
+ /* Return the value for __GCC_IEC_559_COMPLEX.  */
+ static int
+ cpp_iec_559_complex_value (void)
+ {
+   /* The value is no bigger than that of __GCC_IEC_559.  */
+   int ret = cpp_iec_559_value ();
+   /* Some options are contrary to the required default state of the
+      CX_LIMITED_RANGE pragma.  */
+   if (flag_complex_method != 2)
+     ret = 0;
+   return ret;
+ }
  /* Hook that registers front end and target-specific built-ins.  */
  void
  c_cpp_builtins (cpp_reader *pfile)
    /* stdint.h and the testsuite need to know these.  */
    builtin_define_stdint_macros ();
  
+   /* Provide information for library headers to determine whether to
+      define macros such as __STDC_IEC_559__ and
+      __STDC_IEC_559_COMPLEX__.  */
+   builtin_define_with_int_value ("__GCC_IEC_559", cpp_iec_559_value ());
+   builtin_define_with_int_value ("__GCC_IEC_559_COMPLEX",
+                                cpp_iec_559_complex_value ());
    /* float.h needs to know this.  */
    builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
                                 TARGET_FLT_EVAL_METHOD);
diff --combined gcc/c-family/c-format.c
index e5847021b83a099f584de78dbaf5202ad797f45e,f0371d3cb6ec200d139c498eb155cf8718bcbf55..0ba9085bcd10425e2459db14f06a69edd39c57a0
@@@ -226,13 -226,13 +226,13 @@@ check_format_string (tree fntype, unsig
  static bool
  get_constant (tree expr, unsigned HOST_WIDE_INT *value, int validated_p)
  {
 -  if (TREE_CODE (expr) != INTEGER_CST || TREE_INT_CST_HIGH (expr) != 0)
 +  if (!cst_fits_uhwi_p (expr))
      {
        gcc_assert (!validated_p);
        return false;
      }
  
 -  *value = TREE_INT_CST_LOW (expr);
 +  *value = tree_to_hwi (expr);
  
    return true;
  }
@@@ -721,7 -721,7 +721,7 @@@ static const format_char_info gcc_cxxdi
    /* Custom conversion specifiers.  */
  
    /* These will require a "tree" at runtime.  */
-   { "ADEFKSTV",0,STD_C89,{ T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+#",   "",   NULL },
+   { "ADEFKSTVX",0,STD_C89,{ T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+#",   "",   NULL },
  
    { "v", 0,STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q#",  "",   NULL },
  
@@@ -1459,8 -1459,8 +1459,8 @@@ check_format_arg (void *ctx, tree forma
          res->number_non_literal++;
          return;
        }
 -      if (!host_integerp (arg1, 0)
 -        || (offset = tree_low_cst (arg1, 0)) < 0)
 +      if (!tree_fits_shwi_p (arg1)
 +        || (offset = tree_to_shwi (arg1)) < 0)
        {
          res->number_non_literal++;
          return;
        return;
      }
    if (TREE_CODE (format_tree) == ARRAY_REF
 -      && host_integerp (TREE_OPERAND (format_tree, 1), 0)
 -      && (offset += tree_low_cst (TREE_OPERAND (format_tree, 1), 0)) >= 0)
 +      && tree_fits_shwi_p (TREE_OPERAND (format_tree, 1))
 +      && (offset += tree_to_shwi (TREE_OPERAND (format_tree, 1))) >= 0)
      format_tree = TREE_OPERAND (format_tree, 0);
    if (TREE_CODE (format_tree) == VAR_DECL
        && TREE_CODE (TREE_TYPE (format_tree)) == ARRAY_TYPE
        /* Variable length arrays can't be initialized.  */
        gcc_assert (TREE_CODE (array_size) == INTEGER_CST);
  
 -      if (host_integerp (array_size, 0))
 +      if (tree_fits_shwi_p (array_size))
        {
 -        HOST_WIDE_INT array_size_value = TREE_INT_CST_LOW (array_size);
 +        HOST_WIDE_INT array_size_value = tree_to_shwi (array_size);
          if (array_size_value > 0
              && array_size_value == (int) array_size_value
              && format_length > array_size_value)
diff --combined gcc/c-family/c-lex.c
index 367bed635a16e41f38d619c8fc4d7f9ff9ecb406,6484352f4c61bf6ddcfff137cc6fc4bb20a928c2..4aff46db23889ef3d3fae68a11c08f7b82ac2825
@@@ -33,7 -33,6 +33,7 @@@ along with GCC; see the file COPYING3
  #include "splay-tree.h"
  #include "debug.h"
  #include "target.h"
 +#include "wide-int.h"
  
  /* We may keep statistics about how long which files took to compile.  */
  static int header_time, body_time;
@@@ -48,9 -47,9 +48,9 @@@ static tree interpret_float (const cpp_
                             enum overflow_type *);
  static tree interpret_fixed (const cpp_token *, unsigned int);
  static enum integer_type_kind narrowest_unsigned_type
 -      (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned int);
 +      (const widest_int &, unsigned int);
  static enum integer_type_kind narrowest_signed_type
 -      (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned int);
 +      (const widest_int &, unsigned int);
  static enum cpp_ttype lex_string (const cpp_token *, tree *, bool, bool);
  static tree lex_charconst (const cpp_token *);
  static void update_header_times (const char *);
@@@ -526,7 -525,9 +526,7 @@@ c_lex_with_flags (tree *value, location
     there isn't one.  */
  
  static enum integer_type_kind
 -narrowest_unsigned_type (unsigned HOST_WIDE_INT low,
 -                       unsigned HOST_WIDE_INT high,
 -                       unsigned int flags)
 +narrowest_unsigned_type (const widest_int &val, unsigned int flags)
  {
    int itk;
  
        continue;
        upper = TYPE_MAX_VALUE (integer_types[itk]);
  
 -      if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (upper) > high
 -        || ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (upper) == high
 -            && TREE_INT_CST_LOW (upper) >= low))
 +      if (wi::geu_p (wi::to_widest (upper), val))
        return (enum integer_type_kind) itk;
      }
  
  
  /* Ditto, but narrowest signed type.  */
  static enum integer_type_kind
 -narrowest_signed_type (unsigned HOST_WIDE_INT low,
 -                     unsigned HOST_WIDE_INT high, unsigned int flags)
 +narrowest_signed_type (const widest_int &val, unsigned int flags)
  {
    int itk;
  
    else
      itk = itk_long_long;
  
 -
    for (; itk < itk_none; itk += 2 /* skip signed types */)
      {
        tree upper;
        continue;
        upper = TYPE_MAX_VALUE (integer_types[itk]);
  
 -      if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (upper) > high
 -        || ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (upper) == high
 -            && TREE_INT_CST_LOW (upper) >= low))
 +      if (wi::geu_p (wi::to_widest (upper), val))
        return (enum integer_type_kind) itk;
      }
  
@@@ -588,7 -595,6 +588,7 @@@ interpret_integer (const cpp_token *tok
    tree value, type;
    enum integer_type_kind itk;
    cpp_num integer;
 +  HOST_WIDE_INT ival[3];
  
    *overflow = OT_NONE;
  
    if (integer.overflow)
      *overflow = OT_OVERFLOW;
  
 +  ival[0] = integer.low;
 +  ival[1] = integer.high;
 +  ival[2] = 0;
 +  widest_int wval = widest_int::from_array (ival, 3);
 +
    /* The type of a constant with a U suffix is straightforward.  */
    if (flags & CPP_N_UNSIGNED)
 -    itk = narrowest_unsigned_type (integer.low, integer.high, flags);
 +    itk = narrowest_unsigned_type (wval, flags);
    else
      {
        /* The type of a potentially-signed integer constant varies
         depending on the base it's in, the standard in use, and the
         length suffixes.  */
        enum integer_type_kind itk_u
 -      = narrowest_unsigned_type (integer.low, integer.high, flags);
 +      = narrowest_unsigned_type (wval, flags);
        enum integer_type_kind itk_s
 -      = narrowest_signed_type (integer.low, integer.high, flags);
 +      = narrowest_signed_type (wval, flags);
  
        /* In both C89 and C99, octal and hex constants may be signed or
         unsigned, whichever fits tighter.  We do not warn about this
           : "integer constant is too large for %<long%> type");
      }
  
 -  value = build_int_cst_wide (type, integer.low, integer.high);
 +  value = wide_int_to_tree (type, wval);
  
    /* Convert imaginary to a complex type.  */
    if (flags & CPP_N_IMAGINARY)
@@@ -773,8 -774,19 +773,19 @@@ interpret_float (const cpp_token *token
      }
  
    copy = (char *) alloca (copylen + 1);
-   memcpy (copy, token->val.str.text, copylen);
-   copy[copylen] = '\0';
+   if (cxx_dialect > cxx11)
+     {
+       size_t maxlen = 0;
+       for (size_t i = 0; i < copylen; ++i)
+         if (token->val.str.text[i] != '\'')
+           copy[maxlen++] = token->val.str.text[i];
+       copy[maxlen] = '\0';
+     }
+   else
+     {
+       memcpy (copy, token->val.str.text, copylen);
+       copy[copylen] = '\0';
+     }
  
    real_from_string3 (&real, copy, TYPE_MODE (const_type));
    if (const_type != type)
@@@ -1151,9 -1163,9 +1162,9 @@@ lex_charconst (const cpp_token *token
    /* Cast to cppchar_signed_t to get correct sign-extension of RESULT
       before possibly widening to HOST_WIDE_INT for build_int_cst.  */
    if (unsignedp || (cppchar_signed_t) result >= 0)
 -    value = build_int_cst_wide (type, result, 0);
 +    value = build_int_cst (type, result);
    else
 -    value = build_int_cst_wide (type, (cppchar_signed_t) result, -1);
 +    value = build_int_cst (type, (cppchar_signed_t) result);
  
    return value;
  }
diff --combined gcc/c-family/c-pragma.c
index abbb0cbaf6eb0eb0611c8813cd14685e0ddfbaab,3ce77a2e91aabec6dfdd217e55cf255441588d5d..8915f441d7d85c1db9e8876652ea5f9eab256044
@@@ -151,8 -151,7 +151,8 @@@ handle_pragma_pack (cpp_reader * ARG_UN
      {
        if (TREE_CODE (x) != INTEGER_CST)
        GCC_BAD ("invalid constant in %<#pragma pack%> - ignored");
 -      align = TREE_INT_CST_LOW (x);
 +      /* Cannot use tree_to_uhwi here or it will ice if above message printed.  */
 +      align = tree_to_hwi (x);
        action = set;
        if (pragma_lex (&x) != CPP_CLOSE_PAREN)
        GCC_BAD ("malformed %<#pragma pack%> - ignored");
            {
              if (TREE_CODE (x) != INTEGER_CST)
                GCC_BAD ("invalid constant in %<#pragma pack%> - ignored");
 -            align = TREE_INT_CST_LOW (x);
 +            /* Cannot use tree_to_uhwi here or it will ice if above message printed.  */
 +            align = tree_to_hwi (x);
              if (align == -1)
                action = set;
            }
@@@ -309,7 -307,7 +309,7 @@@ maybe_apply_pending_pragma_weaks (void
    tree alias_id, id, decl;
    int i;
    pending_weak *pe;
-   symtab_node target;
+   symtab_node *target;
  
    if (!pending_weaks)
      return;
  
        target = symtab_node_for_asm (id);
        decl = build_decl (UNKNOWN_LOCATION,
-                        target ? TREE_CODE (target->symbol.decl) : FUNCTION_DECL,
+                        target ? TREE_CODE (target->decl) : FUNCTION_DECL,
                         alias_id, default_function_type);
  
        DECL_ARTIFICIAL (decl) = 1;
@@@ -1364,6 -1362,8 +1364,8 @@@ init_pragma (void
      cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
                                  PRAGMA_GCC_PCH_PREPROCESS, false, false);
  
+   cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false,
+                               false);
  #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
    c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
  #else
diff --combined gcc/c-family/cilk.c
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 --combined gcc/c/c-decl.c
index c99db13ff848175d1660fda2cdea6f447b44ef14,2833fdba48675ba1d6896d2412e05b6ef07f9f4d..9b077f4fa92a33695c3d2ecd640d6d6c1f156f92
@@@ -45,6 -45,7 +45,7 @@@ along with GCC; see the file COPYING3
  #include "c-family/c-common.h"
  #include "c-family/c-objc.h"
  #include "c-family/c-pragma.h"
+ #include "c-family/c-ubsan.h"
  #include "c-lang.h"
  #include "langhooks.h"
  #include "tree-iterator.h"
@@@ -56,6 -57,7 +57,7 @@@
  #include "pointer-set.h"
  #include "plugin.h"
  #include "c-family/c-ada-spec.h"
+ #include "cilk.h"
  
  /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
  enum decl_context
@@@ -4819,14 -4821,14 +4821,14 @@@ check_bitfield_type_and_width (tree *ty
        *width = build_int_cst (integer_type_node, w);
      }
    else
 -    w = tree_low_cst (*width, 1);
 +    w = tree_to_uhwi (*width);
  
    if (TREE_CODE (*type) == ENUMERAL_TYPE)
      {
        struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
        if (!lt
 -        || w < tree_int_cst_min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
 -        || w < tree_int_cst_min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
 +        || w < tree_int_cst_min_precision (lt->enum_min, TYPE_SIGN (*type))
 +        || w < tree_int_cst_min_precision (lt->enum_max, TYPE_SIGN (*type)))
        warning (0, "%qs is narrower than values of its type", name);
      }
  }
@@@ -5410,6 -5412,16 +5412,16 @@@ grokdeclarator (const struct c_declarat
                       with known value.  */
                    this_size_varies = size_varies = true;
                    warn_variable_length_array (name, size);
+                   if (flag_sanitize & SANITIZE_VLA
+                       && decl_context == NORMAL)
+                     {
+                       /* Evaluate the array size only once.  */
+                       size = c_save_expr (size);
+                       size = c_fully_fold (size, false, NULL);
+                       size = fold_build2 (COMPOUND_EXPR, TREE_TYPE (size),
+                                           ubsan_instrument_vla (loc, size),
+                                           size);
+                     }
                  }
  
                if (integer_zerop (size) && !this_size_varies)
        else
        error_at (loc, "size of unnamed array is too large");
        /* If we proceed with the array type as it is, we'll eventually
 -       crash in tree_low_cst().  */
 +       crash in tree_to_uhwi ().  */
        type = error_mark_node;
      }
  
@@@ -7182,7 -7194,7 +7194,7 @@@ finish_struct (location_t loc, tree t, 
  
        if (DECL_INITIAL (x))
        {
 -        unsigned HOST_WIDE_INT width = tree_low_cst (DECL_INITIAL (x), 1);
 +        unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (x));
          DECL_SIZE (x) = bitsize_int (width);
          DECL_BIT_FIELD (x) = 1;
          SET_DECL_C_BIT_FIELD (x);
          && TREE_TYPE (*fieldlistp) != error_mark_node)
        {
          unsigned HOST_WIDE_INT width
 -          = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
 +          = tree_to_uhwi (DECL_INITIAL (*fieldlistp));
          tree type = TREE_TYPE (*fieldlistp);
          if (width != TYPE_PRECISION (type))
            {
@@@ -7479,8 -7491,7 +7491,8 @@@ finish_enum (tree enumtype, tree values
  {
    tree pair, tem;
    tree minnode = 0, maxnode = 0;
 -  int precision, unsign;
 +  int precision; 
 +  signop sign;
    bool toplevel = (file_scope == current_scope);
    struct lang_type *lt;
  
       as one of the integral types - the narrowest one that fits, except
       that normally we only go as narrow as int - and signed iff any of
       the values are negative.  */
 -  unsign = (tree_int_cst_sgn (minnode) >= 0);
 -  precision = MAX (tree_int_cst_min_precision (minnode, unsign),
 -                 tree_int_cst_min_precision (maxnode, unsign));
 +  sign = (tree_int_cst_sgn (minnode) >= 0) ? UNSIGNED : SIGNED;
 +  precision = MAX (tree_int_cst_min_precision (minnode, sign),
 +                 tree_int_cst_min_precision (maxnode, sign));
  
    if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
      {
 -      tem = c_common_type_for_size (precision, unsign);
 +      tem = c_common_type_for_size (precision, sign == UNSIGNED ? 1 : 0);
        if (tem == NULL)
        {
          warning (0, "enumeration values exceed range of largest integer");
        }
      }
    else
 -    tem = unsign ? unsigned_type_node : integer_type_node;
 +    tem = sign == UNSIGNED ? unsigned_type_node : integer_type_node;
  
    TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
    TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
@@@ -8448,6 -8459,12 +8460,12 @@@ finish_function (void
    /* Tie off the statement tree for this function.  */
    DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
  
+   /* If the function has _Cilk_spawn in front of a function call inside it
+      i.e. it is a spawning function, then add the appropriate Cilk plus
+      functions inside.  */
+   if (fn_contains_cilk_spawn_p (cfun))
+     cfun->cilk_frame_decl = insert_cilk_frame (fndecl);
    finish_fname_decls ();
  
    /* Complain if there's just no return statement.  */
diff --combined gcc/c/c-parser.c
index f8b737b02fb22b0a0335d5b6c047256a8a4ded13,a8f4774136d3875e9af0e70d74631d50df6af403..6f52ba94e77a0a09eb1500b367a087203bb55331
@@@ -383,7 -383,7 +383,7 @@@ c_lex_one_token (c_parser *parser, c_to
        break;
      case CPP_PRAGMA:
        /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
 -      token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
 +      token->pragma_kind = (enum pragma_kind) tree_to_hwi (token->value);
        token->value = NULL;
        break;
      default:
@@@ -1157,9 -1157,9 +1157,9 @@@ static void c_parser_statement (c_parse
  static void c_parser_statement_after_labels (c_parser *);
  static void c_parser_if_statement (c_parser *);
  static void c_parser_switch_statement (c_parser *);
- static void c_parser_while_statement (c_parser *);
- static void c_parser_do_statement (c_parser *);
- static void c_parser_for_statement (c_parser *);
+ static void c_parser_while_statement (c_parser *, bool);
+ static void c_parser_do_statement (c_parser *, bool);
+ static void c_parser_for_statement (c_parser *, bool);
  static tree c_parser_asm_statement (c_parser *);
  static tree c_parser_asm_operands (c_parser *);
  static tree c_parser_asm_goto_operands (c_parser *);
@@@ -2645,6 -2645,11 +2645,11 @@@ c_parser_struct_declaration (c_parser *
      }
    specs = build_null_declspecs ();
    decl_loc = c_parser_peek_token (parser)->location;
+   /* Strictly by the standard, we shouldn't allow _Alignas here,
+      but it appears to have been intended to allow it there, so
+      we're keeping it as it is until WG14 reaches a conclusion
+      of N1731.
+      <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf>  */
    c_parser_declspecs (parser, specs, false, true, true,
                      true, cla_nonabstract_decl);
    if (parser->error)
@@@ -2959,7 -2964,7 +2964,7 @@@ c_parser_declarator (c_parser *parser, 
        struct c_declarator *inner;
        c_parser_consume_token (parser);
        c_parser_declspecs (parser, quals_attrs, false, false, true,
-                         true, cla_prefer_id);
+                         false, cla_prefer_id);
        inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
        if (inner == NULL)
        return NULL;
@@@ -4574,13 -4579,21 +4579,21 @@@ c_parser_statement_after_labels (c_pars
          c_parser_switch_statement (parser);
          break;
        case RID_WHILE:
-         c_parser_while_statement (parser);
+         c_parser_while_statement (parser, false);
          break;
        case RID_DO:
-         c_parser_do_statement (parser);
+         c_parser_do_statement (parser, false);
          break;
        case RID_FOR:
-         c_parser_for_statement (parser);
+         c_parser_for_statement (parser, false);
+         break;
+       case RID_CILK_SYNC:
+         c_parser_consume_token (parser);
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+         if (!flag_enable_cilkplus) 
+           error_at (loc, "-fcilkplus must be enabled to use %<_Cilk_sync%>");
+         else 
+           add_stmt (build_cilk_sync ());
          break;
        case RID_GOTO:
          c_parser_consume_token (parser);
@@@ -4907,7 -4920,7 +4920,7 @@@ c_parser_switch_statement (c_parser *pa
  */
  
  static void
- c_parser_while_statement (c_parser *parser)
+ c_parser_while_statement (c_parser *parser, bool ivdep)
  {
    tree block, cond, body, save_break, save_cont;
    location_t loc;
                "statement");
        cond = error_mark_node;
      }
+   if (ivdep && cond != error_mark_node)
+     cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+                  build_int_cst (integer_type_node,
+                  annot_expr_ivdep_kind));
    save_break = c_break_label;
    c_break_label = NULL_TREE;
    save_cont = c_cont_label;
  */
  
  static void
- c_parser_do_statement (c_parser *parser)
+ c_parser_do_statement (c_parser *parser, bool ivdep)
  {
    tree block, cond, body, save_break, save_cont, new_break, new_cont;
    location_t loc;
                "do-while statement");
        cond = error_mark_node;
      }
+   if (ivdep && cond != error_mark_node)
+     cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+                  build_int_cst (integer_type_node,
+                  annot_expr_ivdep_kind));
    if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
      c_parser_skip_to_end_of_block_or_statement (parser);
    c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
  */
  
  static void
- c_parser_for_statement (c_parser *parser)
+ c_parser_for_statement (c_parser *parser, bool ivdep)
  {
    tree block, cond, incr, save_break, save_cont, body;
    /* The following are only used when parsing an ObjC foreach statement.  */
        {
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             c_parser_consume_token (parser);
-             cond = NULL_TREE;
+             if (ivdep)
+               {
+                 c_parser_error (parser, "missing loop condition in loop with "
+                                 "%<GCC ivdep%> pragma");
+                 cond = error_mark_node;
+               }
+             else
+               {
+                 c_parser_consume_token (parser);
+                 cond = NULL_TREE;
+               }
            }
          else
            {
              c_parser_skip_until_found (parser, CPP_SEMICOLON,
                                         "expected %<;%>");
            }
+         if (ivdep && cond != error_mark_node)
+           cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+                          build_int_cst (integer_type_node,
+                          annot_expr_ivdep_kind));
        }
        /* Parse the increment expression (the third expression in a
         for-statement).  In the case of a foreach-statement, this is
@@@ -7148,6 -7182,30 +7182,30 @@@ c_parser_postfix_expression (c_parser *
        case RID_GENERIC:
          expr = c_parser_generic_selection (parser);
          break;
+       case RID_CILK_SPAWN:
+         c_parser_consume_token (parser);
+         if (!flag_enable_cilkplus)
+           {
+             error_at (loc, "-fcilkplus must be enabled to use "
+                       "%<_Cilk_spawn%>");
+             expr = c_parser_postfix_expression (parser);
+             expr.value = error_mark_node;           
+           }
+         if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN)
+           {
+             error_at (loc, "consecutive %<_Cilk_spawn%> keywords "
+                       "are not permitted");
+             /* Now flush out all the _Cilk_spawns.  */
+             while (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN)
+               c_parser_consume_token (parser);
+             expr = c_parser_postfix_expression (parser);
+           }
+         else
+           {
+             expr = c_parser_postfix_expression (parser);
+             expr.value = build_cilk_spawn (loc, expr.value);
+           }
+         break; 
        default:
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
@@@ -9081,6 -9139,23 +9139,23 @@@ c_parser_pragma (c_parser *parser, enu
      case PRAGMA_OMP_DECLARE_REDUCTION:
        c_parser_omp_declare (parser, context);
        return false;
+     case PRAGMA_IVDEP:
+       c_parser_consume_pragma (parser);
+       c_parser_skip_to_pragma_eol (parser);
+       if (!c_parser_next_token_is_keyword (parser, RID_FOR)
+         && !c_parser_next_token_is_keyword (parser, RID_WHILE)
+         && !c_parser_next_token_is_keyword (parser, RID_DO))
+       {
+         c_parser_error (parser, "for, while or do statement expected");
+         return false;
+       }
+       if (c_parser_next_token_is_keyword (parser, RID_FOR))
+       c_parser_for_statement (parser, true);
+       else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
+       c_parser_while_statement (parser, true);
+       else
+       c_parser_do_statement (parser, true);
+       return false;
  
      case PRAGMA_GCC_PCH_PREPROCESS:
        c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
@@@ -9442,8 -9517,8 +9517,8 @@@ c_parser_omp_clause_collapse (c_parser 
    mark_exp_read (num);
    num = c_fully_fold (num, false, NULL);
    if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
 -      || !host_integerp (num, 0)
 -      || (n = tree_low_cst (num, 0)) <= 0
 +      || !tree_fits_shwi_p (num)
 +      || (n = tree_to_shwi (num)) <= 0
        || (int) n != n)
      {
        error_at (loc,
@@@ -11169,7 -11244,7 +11244,7 @@@ c_parser_omp_for_loop (location_t loc, 
  
    for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
      if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
 -      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
 +      collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
  
    gcc_assert (collapse >= 1);
  
diff --combined gcc/c/c-typeck.c
index 90318ba8ae4394f1e57a449f6d53e3e47e3c6536,8f1d3a4837aa410aeb16dc151d7f9e1fcf109fe9..38207593187da0238a725d364e2a6eab72d0719f
@@@ -42,7 -42,6 +42,7 @@@ along with GCC; see the file COPYING3
  #include "c-family/c-objc.h"
  #include "c-family/c-common.h"
  #include "c-family/c-ubsan.h"
 +#include "wide-int.h"
  
  /* Possible cases of implicit bad conversions.  Used to select
     diagnostic messages in convert_for_assignment.  */
@@@ -4388,6 -4387,14 +4388,14 @@@ build_compound_expr (location_t loc, tr
    tree eptype = NULL_TREE;
    tree ret;
  
+   if (flag_enable_cilkplus
+       && (TREE_CODE (expr1) == CILK_SPAWN_STMT
+         || TREE_CODE (expr2) == CILK_SPAWN_STMT))
+     {
+       error_at (loc,
+               "spawned function call cannot be part of a comma expression");
+       return error_mark_node;
+     }
    expr1_int_operands = EXPR_INT_CONST_OPERANDS (expr1);
    if (expr1_int_operands)
      expr1 = remove_c_maybe_const_expr (expr1);
@@@ -4749,8 -4756,9 +4757,8 @@@ build_c_cast (location_t loc, tree type
            }
          else if (TREE_OVERFLOW (value))
            /* Reset VALUE's overflow flags, ensuring constant sharing.  */
 -          value = build_int_cst_wide (TREE_TYPE (value),
 -                                      TREE_INT_CST_LOW (value),
 -                                      TREE_INT_CST_HIGH (value));
 +          value = wide_int_to_tree (TREE_TYPE (value),
 +                                    value);
        }
      }
  
@@@ -6810,7 -6818,7 +6818,7 @@@ push_init_level (int implicit, struct o
    else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
      {
        constructor_type = TREE_TYPE (constructor_type);
 -      push_array_bounds (tree_low_cst (constructor_index, 1));
 +      push_array_bounds (tree_to_uhwi (constructor_index));
        constructor_depth++;
      }
  
@@@ -7609,20 -7617,20 +7617,20 @@@ set_nonincremental_init_from_string (tr
      {
        if (wchar_bytes == 1)
        {
 -        val[1] = (unsigned char) *p++;
 -        val[0] = 0;
 +        val[0] = (unsigned char) *p++;
 +        val[1] = 0;
        }
        else
        {
 -        val[0] = 0;
          val[1] = 0;
 +        val[0] = 0;
          for (byte = 0; byte < wchar_bytes; byte++)
            {
              if (BYTES_BIG_ENDIAN)
                bitpos = (wchar_bytes - byte - 1) * charwidth;
              else
                bitpos = byte * charwidth;
 -            val[bitpos < HOST_BITS_PER_WIDE_INT]
 +            val[bitpos % HOST_BITS_PER_WIDE_INT]
                |= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++))
                   << (bitpos % HOST_BITS_PER_WIDE_INT);
            }
          bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
          if (bitpos < HOST_BITS_PER_WIDE_INT)
            {
 -            if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
 +            if (val[0] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
                {
 -                val[1] |= ((HOST_WIDE_INT) -1) << bitpos;
 -                val[0] = -1;
 +                val[0] |= ((HOST_WIDE_INT) -1) << bitpos;
 +                val[1] = -1;
                }
            }
          else if (bitpos == HOST_BITS_PER_WIDE_INT)
            {
 -            if (val[1] < 0)
 -              val[0] = -1;
 +            if (val[0] < 0)
 +              val[1] = -1;
            }
 -        else if (val[0] & (((HOST_WIDE_INT) 1)
 +        else if (val[1] & (((HOST_WIDE_INT) 1)
                             << (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
 -          val[0] |= ((HOST_WIDE_INT) -1)
 +          val[1] |= ((HOST_WIDE_INT) -1)
                      << (bitpos - HOST_BITS_PER_WIDE_INT);
        }
  
 -      value = build_int_cst_wide (type, val[1], val[0]);
 +      value = wide_int_to_tree (type, 
 +                              wide_int::from_array (val, 2, 
 +                                                    HOST_BITS_PER_WIDE_INT * 2));
        add_pending_init (purpose, value, NULL_TREE, true,
                          braced_init_obstack);
      }
@@@ -8362,7 -8368,7 +8370,7 @@@ process_init_element (struct c_expr val
          /* Now output the actual element.  */
          if (value.value)
            {
 -            push_array_bounds (tree_low_cst (constructor_index, 1));
 +            push_array_bounds (tree_to_uhwi (constructor_index));
              output_init_element (value.value, value.original_type,
                                   strict_string, elttype,
                                   constructor_index, 1, implicit,
@@@ -8696,6 -8702,12 +8704,12 @@@ c_finish_return (location_t loc, tree r
          return error_mark_node;
        }
      }
+   if (flag_enable_cilkplus && retval && TREE_CODE (retval) == CILK_SPAWN_STMT)
+     {
+       error_at (loc, "use of %<_Cilk_spawn%> in a return statement is not "
+               "allowed");
+       return error_mark_node;
+     }
    if (retval)
      {
        tree semantic_type = NULL_TREE;
@@@ -9158,7 -9170,7 +9172,7 @@@ c_finish_bc_stmt (location_t loc, tree 
      }
    else if (TREE_CODE (label) == LABEL_DECL)
      ;
 -  else switch (TREE_INT_CST_LOW (label))
 +  else switch (tree_to_hwi (label))
      {
      case 0:
        if (is_break)
@@@ -11304,6 -11316,7 +11318,7 @@@ c_finish_omp_clauses (tree clauses
                            "%qE has invalid type for %<reduction(%s)%>",
                            t, r_name);
                  remove = true;
+                 break;
                }
            }
          else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == error_mark_node)
              error_at (OMP_CLAUSE_LOCATION (c),
                        "user defined reduction not found for %qD", t);
              remove = true;
+             break;
            }
          else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
            {
              error_at (OMP_CLAUSE_LOCATION (c),
                        "%qE must be %<threadprivate%> for %<copyin%>", t);
              remove = true;
+             break;
            }
          goto check_dup_generic;
  
                        "%qE is not a variable in %<aligned%> clause", t);
              remove = true;
            }
+         else if (!POINTER_TYPE_P (TREE_TYPE (t))
+                  && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE in %<aligned%> clause is neither a pointer nor "
+                       "an array", t);
+             remove = true;
+           }
          else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
            {
              error_at (OMP_CLAUSE_LOCATION (c),
                error_at (OMP_CLAUSE_LOCATION (c),
                          "%qE is not an argument in %<uniform%> clause", t);
              remove = true;
+             break;
            }
-         break;
+         goto check_dup_generic;
  
        case OMP_CLAUSE_NOWAIT:
          if (copyprivate_seen)
@@@ -11830,7 -11854,8 +11856,7 @@@ c_tree_equal (tree t1, tree t2
    switch (code1)
      {
      case INTEGER_CST:
 -      return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
 -      && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
 +      return wi::eq_p (t1, t2);
  
      case REAL_CST:
        return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
diff --combined gcc/cfgexpand.c
index 7531c2cf6c0d25378a21bfba69261e2e1fa3a321,fb05ce7a05d3dadb1d2bd8b7e6d9856e1dc5a4e5..dbd77d89b1673473e7905c74f5c860d52bfe694e
@@@ -28,6 -28,15 +28,15 @@@ along with GCC; see the file COPYING3
  #include "function.h"
  #include "expr.h"
  #include "langhooks.h"
+ #include "bitmap.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "tree-pass.h"
  #include "except.h"
@@@ -40,8 -49,8 +49,8 @@@
  #include "tree-inline.h"
  #include "value-prof.h"
  #include "target.h"
+ #include "tree-ssa-live.h"
  #include "tree-outof-ssa.h"
- #include "bitmap.h"
  #include "sbitmap.h"
  #include "cfgloop.h"
  #include "regs.h" /* For reg_renumber.  */
@@@ -271,7 -280,7 +280,7 @@@ add_stack_var (tree decl
    * (size_t *)pointer_map_insert (decl_to_stack_part, decl) = stack_vars_num;
  
    v->decl = decl;
 -  v->size = tree_low_cst (DECL_SIZE_UNIT (SSAVAR (decl)), 1);
 +  v->size = tree_to_uhwi (DECL_SIZE_UNIT (SSAVAR (decl)));
    /* Ensure that all variables have size, so that &a != &b for any two
       variables that are simultaneously live.  */
    if (v->size == 0)
@@@ -1035,7 -1044,7 +1044,7 @@@ expand_one_stack_var (tree var
    HOST_WIDE_INT size, offset;
    unsigned byte_align;
  
 -  size = tree_low_cst (DECL_SIZE_UNIT (SSAVAR (var)), 1);
 +  size = tree_to_uhwi (DECL_SIZE_UNIT (SSAVAR (var)));
    byte_align = align_local_variable (SSAVAR (var));
  
    /* We handle highly aligned variables in expand_stack_vars.  */
@@@ -1133,8 -1142,8 +1142,8 @@@ defer_stack_allocation (tree var, bool 
       get completely out of hand.  So we avoid adding scalars and
       "small" aggregates to the list at all.  */
    if (optimize == 0
 -      && (tree_low_cst (DECL_SIZE_UNIT (var), 1)
 -          < PARAM_VALUE (PARAM_MIN_SIZE_FOR_STACK_SHARING)))
 +      && (tree_to_uhwi (DECL_SIZE_UNIT (var))
 +          < (unsigned HOST_WIDE_INT)PARAM_VALUE (PARAM_MIN_SIZE_FOR_STACK_SHARING)))
      return false;
  
    return true;
@@@ -1248,7 -1257,7 +1257,7 @@@ expand_one_var (tree var, bool toplevel
      {
        if (really_expand)
          expand_one_stack_var (origvar);
 -      return tree_low_cst (DECL_SIZE_UNIT (var), 1);
 +      return tree_to_uhwi (DECL_SIZE_UNIT (var));
      }
    return 0;
  }
@@@ -1325,10 -1334,10 +1334,10 @@@ stack_protect_classify_type (tree type
          unsigned HOST_WIDE_INT len;
  
          if (!TYPE_SIZE_UNIT (type)
 -            || !host_integerp (TYPE_SIZE_UNIT (type), 1))
 +            || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
            len = max;
          else
 -          len = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
 +          len = tree_to_uhwi (TYPE_SIZE_UNIT (type));
  
          if (len < max)
            ret = SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_ARRAY;
@@@ -1500,7 -1509,7 +1509,7 @@@ estimated_stack_frame_size (struct cgra
    HOST_WIDE_INT size = 0;
    size_t i;
    tree var;
-   struct function *fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
+   struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
  
    push_cfun (fn);
  
@@@ -4781,14 -4790,18 +4790,18 @@@ gimple_expand_cfg (void
          if (e->insns.r)
            {
              rebuild_jump_labels_chain (e->insns.r);
-             /* Avoid putting insns before parm_birth_insn.  */
+             /* Put insns after parm birth, but before
+                NOTE_INSNS_FUNCTION_BEG.  */
              if (e->src == ENTRY_BLOCK_PTR
-                 && single_succ_p (ENTRY_BLOCK_PTR)
-                 && parm_birth_insn)
+                 && single_succ_p (ENTRY_BLOCK_PTR))
                {
                  rtx insns = e->insns.r;
                  e->insns.r = NULL_RTX;
-                 emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
+                 if (NOTE_P (parm_birth_insn)
+                     && NOTE_KIND (parm_birth_insn) == NOTE_INSN_FUNCTION_BEG)
+                   emit_insn_before_noloc (insns, parm_birth_insn, e->dest);
+                 else
+                   emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
                }
              else
                commit_one_edge_insertion (e);
diff --combined gcc/cfgloop.c
index a894793b2f6fd6705eea8d88aabc80cbecab1d58,3ff8e841bac098f669eb89017a9faaa3e8faca0e..72441ceefe046fd7c4cfeabae2134ba802a11040
@@@ -28,7 -28,8 +28,8 @@@ along with GCC; see the file COPYING3
  #include "diagnostic-core.h"
  #include "flags.h"
  #include "tree.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
  #include "pointer-set.h"
  #include "ggc.h"
  #include "dumpfile.h"
@@@ -332,8 -333,7 +333,8 @@@ alloc_loop (void
    loop->exits = ggc_alloc_cleared_loop_exit ();
    loop->exits->next = loop->exits->prev = loop->exits;
    loop->can_be_parallel = false;
 -
 +  loop->nb_iterations_upper_bound = 0;
 +  loop->nb_iterations_estimate = 0;
    return loop;
  }
  
@@@ -1788,21 -1788,21 +1789,21 @@@ get_loop_location (struct loop *loop
     I_BOUND times.  */
  
  void
 -record_niter_bound (struct loop *loop, double_int i_bound, bool realistic,
 -                  bool upper)
 +record_niter_bound (struct loop *loop, const widest_int &i_bound,
 +                  bool realistic, bool upper)
  {
    /* Update the bounds only when there is no previous estimation, or when the
       current estimation is smaller.  */
    if (upper
        && (!loop->any_upper_bound
 -        || i_bound.ult (loop->nb_iterations_upper_bound)))
 +        || wi::ltu_p (i_bound, loop->nb_iterations_upper_bound)))
      {
        loop->any_upper_bound = true;
        loop->nb_iterations_upper_bound = i_bound;
      }
    if (realistic
        && (!loop->any_estimate
 -        || i_bound.ult (loop->nb_iterations_estimate)))
 +        || wi::ltu_p (i_bound, loop->nb_iterations_estimate)))
      {
        loop->any_estimate = true;
        loop->nb_iterations_estimate = i_bound;
       number of iterations, use the upper bound instead.  */
    if (loop->any_upper_bound
        && loop->any_estimate
 -      && loop->nb_iterations_upper_bound.ult (loop->nb_iterations_estimate))
 +      && wi::ltu_p (loop->nb_iterations_upper_bound,
 +                  loop->nb_iterations_estimate))
      loop->nb_iterations_estimate = loop->nb_iterations_upper_bound;
  }
  
  HOST_WIDE_INT
  get_estimated_loop_iterations_int (struct loop *loop)
  {
 -  double_int nit;
 +  widest_int nit;
    HOST_WIDE_INT hwi_nit;
  
    if (!get_estimated_loop_iterations (loop, &nit))
      return -1;
  
 -  if (!nit.fits_shwi ())
 +  if (!wi::fits_shwi_p (nit))
      return -1;
    hwi_nit = nit.to_shwi ();
  
@@@ -1861,7 -1860,7 +1862,7 @@@ max_stmt_executions_int (struct loop *l
     returns true.  */
  
  bool
 -get_estimated_loop_iterations (struct loop *loop, double_int *nit)
 +get_estimated_loop_iterations (struct loop *loop, widest_int *nit)
  {
    /* Even if the bound is not recorded, possibly we can derrive one from
       profile.  */
      {
        if (loop->header->count)
        {
 -          *nit = gcov_type_to_double_int
 +          *nit = gcov_type_to_wide_int
                   (expected_loop_iterations_unbounded (loop) + 1);
          return true;
        }
     false, otherwise returns true.  */
  
  bool
 -get_max_loop_iterations (struct loop *loop, double_int *nit)
 +get_max_loop_iterations (struct loop *loop, widest_int *nit)
  {
    if (!loop->any_upper_bound)
      return false;
  HOST_WIDE_INT
  get_max_loop_iterations_int (struct loop *loop)
  {
 -  double_int nit;
 +  widest_int nit;
    HOST_WIDE_INT hwi_nit;
  
    if (!get_max_loop_iterations (loop, &nit))
      return -1;
  
 -  if (!nit.fits_shwi ())
 +  if (!wi::fits_shwi_p (nit))
      return -1;
    hwi_nit = nit.to_shwi ();
  
diff --combined gcc/cgraph.c
index 8eedaa493aaeda45a98d42f1423e89c2e8248e53,f3666fab6dd4c160d17fd694ac18fb1b188ab089..dccd6db3c5685175e8909a7403be652f9dee1f03
@@@ -42,6 -42,9 +42,9 @@@ along with GCC; see the file COPYING3
  #include "gimple.h"
  #include "timevar.h"
  #include "dumpfile.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
  #include "tree-ssa.h"
  #include "value-prof.h"
  #include "except.h"
@@@ -61,7 -64,7 +64,7 @@@ static inline void cgraph_edge_remove_c
  static inline void cgraph_edge_remove_callee (struct cgraph_edge *e);
  
  /* Queue of cgraph nodes scheduled to be lowered.  */
- symtab_node x_cgraph_nodes_queue;
+ symtab_node *x_cgraph_nodes_queue;
  #define cgraph_nodes_queue ((struct cgraph_node *)x_cgraph_nodes_queue)
  
  /* Number of nodes in existence.  */
@@@ -135,7 -138,7 +138,7 @@@ bool cpp_implicit_aliases_done
     The cgraph_function_version_info has a THIS_NODE field that is the
     corresponding cgraph_node..  */
  
- static htab_t GTY((param_is (struct cgraph_function_version_info *)))
+ static GTY((param_is (struct cgraph_function_version_info))) htab_t
    cgraph_fnver_htab = NULL;
  
  /* Hash function for cgraph_fnver_htab.  */
@@@ -271,8 -274,8 +274,8 @@@ record_function_versions (tree decl1, t
  
  /* Macros to access the next item in the list of free cgraph nodes and
     edges. */
- #define NEXT_FREE_NODE(NODE) cgraph ((NODE)->symbol.next)
- #define SET_NEXT_FREE_NODE(NODE,NODE2) ((NODE))->symbol.next = (symtab_node)NODE2
+ #define NEXT_FREE_NODE(NODE) cgraph ((NODE)->next)
+ #define SET_NEXT_FREE_NODE(NODE,NODE2) ((NODE))->next = NODE2
  #define NEXT_FREE_EDGE(EDGE) (EDGE)->prev_caller
  
  /* Register HOOK to be called with DATA on each removed edge.  */
@@@ -510,7 -513,7 +513,7 @@@ cgraph_create_empty_node (void
  {
    struct cgraph_node *node = cgraph_allocate_node ();
  
-   node->symbol.type = SYMTAB_FUNCTION;
+   node->type = SYMTAB_FUNCTION;
    node->frequency = NODE_FREQUENCY_NORMAL;
    node->count_materialization_scale = REG_BR_PROB_BASE;
    cgraph_n_nodes++;
@@@ -525,8 -528,8 +528,8 @@@ cgraph_create_node (tree decl
    struct cgraph_node *node = cgraph_create_empty_node ();
    gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
  
-   node->symbol.decl = decl;
-   symtab_register_node ((symtab_node) node);
+   node->decl = decl;
+   symtab_register_node (node);
  
    if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
      {
@@@ -564,12 -567,12 +567,12 @@@ cgraph_create_function_alias (tree alia
              || TREE_CODE (target) == IDENTIFIER_NODE);
    gcc_assert (TREE_CODE (alias) == FUNCTION_DECL);
    alias_node = cgraph_get_create_node (alias);
-   gcc_assert (!alias_node->symbol.definition);
-   alias_node->symbol.alias_target = target;
-   alias_node->symbol.definition = true;
-   alias_node->symbol.alias = true;
+   gcc_assert (!alias_node->definition);
+   alias_node->alias_target = target;
+   alias_node->definition = true;
+   alias_node->alias = true;
    if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
-     alias_node->symbol.weakref = true;
+     alias_node->weakref = true;
    return alias_node;
  }
  
@@@ -592,10 -595,10 +595,10 @@@ cgraph_same_body_alias (struct cgraph_n
      return NULL;
  
    n = cgraph_create_function_alias (alias, decl);
-   n->symbol.cpp_implicit_alias = true;
+   n->cpp_implicit_alias = true;
    if (cpp_implicit_aliases_done)
-     symtab_resolve_alias ((symtab_node)n,
-                         (symtab_node)cgraph_get_node (decl));
+     symtab_resolve_alias (n,
+                         cgraph_get_node (decl));
    return n;
  }
  
@@@ -616,22 -619,23 +619,22 @@@ cgraph_add_thunk (struct cgraph_node *d
    node = cgraph_get_node (alias);
    if (node)
      {
-       gcc_assert (node->symbol.definition);
-       gcc_assert (!node->symbol.alias);
+       gcc_assert (node->definition);
+       gcc_assert (!node->alias);
        gcc_assert (!node->thunk.thunk_p);
        cgraph_remove_node (node);
      }
    
    node = cgraph_create_node (alias);
    gcc_checking_assert (!virtual_offset
 -                     || tree_to_double_int (virtual_offset) ==
 -                           double_int::from_shwi (virtual_value));
 +                     || wi::eq_p (virtual_offset, virtual_value));
    node->thunk.fixed_offset = fixed_offset;
    node->thunk.this_adjusting = this_adjusting;
    node->thunk.virtual_value = virtual_value;
    node->thunk.virtual_offset_p = virtual_offset != NULL;
    node->thunk.alias = real_alias;
    node->thunk.thunk_p = true;
-   node->symbol.definition = true;
+   node->definition = true;
  
    return node;
  }
@@@ -643,9 -647,9 +646,9 @@@ struct cgraph_node 
  cgraph_node_for_asm (tree asmname)
  {
    /* We do not want to look at inline clones.  */
-   for (symtab_node node = symtab_node_for_asm (asmname);
+   for (symtab_node *node = symtab_node_for_asm (asmname);
         node;
-        node = node->symbol.next_sharing_asm_name)
+        node = node->next_sharing_asm_name)
      {
        cgraph_node *cn = dyn_cast <cgraph_node> (node);
        if (cn && !cn->global.inlined_to)
@@@ -800,7 -804,7 +803,7 @@@ cgraph_set_call_stmt (struct cgraph_edg
        e = cgraph_make_edge_direct (e, new_callee);
      }
  
-   push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl));
+   push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
    e->can_throw_external = stmt_can_throw_external (new_stmt);
    pop_cfun ();
    if (e->caller->call_site_hash)
  
  static struct cgraph_edge *
  cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
-                      gimple call_stmt, gcov_type count, int freq)
+                      gimple call_stmt, gcov_type count, int freq,
+                      bool indir_unknown_callee)
  {
    struct cgraph_edge *edge;
  
    gcc_assert (freq <= CGRAPH_FREQ_MAX);
  
    edge->call_stmt = call_stmt;
-   push_cfun (DECL_STRUCT_FUNCTION (caller->symbol.decl));
+   push_cfun (DECL_STRUCT_FUNCTION (caller->decl));
    edge->can_throw_external
      = call_stmt ? stmt_can_throw_external (call_stmt) : false;
    pop_cfun ();
    if (call_stmt
-       && callee && callee->symbol.decl
-       && !gimple_check_call_matching_types (call_stmt, callee->symbol.decl,
+       && callee && callee->decl
+       && !gimple_check_call_matching_types (call_stmt, callee->decl,
                                            false))
      edge->call_stmt_cannot_inline_p = true;
    else
    edge->indirect_info = NULL;
    edge->indirect_inlining_edge = 0;
    edge->speculative = false;
+   edge->indirect_unknown_callee = indir_unknown_callee;
    if (call_stmt && caller->call_site_hash)
      cgraph_add_edge_to_call_site_hash (edge);
  
@@@ -886,9 -892,8 +891,8 @@@ cgraph_create_edge (struct cgraph_node 
                    gimple call_stmt, gcov_type count, int freq)
  {
    struct cgraph_edge *edge = cgraph_create_edge_1 (caller, callee, call_stmt,
-                                                  count, freq);
+                                                  count, freq, false);
  
-   edge->indirect_unknown_callee = 0;
    initialize_inline_failed (edge);
  
    edge->next_caller = callee->callers;
@@@ -925,10 -930,9 +929,9 @@@ cgraph_create_indirect_edge (struct cgr
                             gcov_type count, int freq)
  {
    struct cgraph_edge *edge = cgraph_create_edge_1 (caller, NULL, call_stmt,
-                                                  count, freq);
+                                                  count, freq, true);
    tree target;
  
-   edge->indirect_unknown_callee = 1;
    initialize_inline_failed (edge);
  
    edge->indirect_info = cgraph_allocate_init_indirect_info ();
        gcc_assert (TREE_CODE (type) == RECORD_TYPE);
        edge->indirect_info->param_index = -1;
        edge->indirect_info->otr_token
 -       = tree_low_cst (OBJ_TYPE_REF_TOKEN (target), 1);
 +       = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
        edge->indirect_info->otr_type = type;
        edge->indirect_info->polymorphic = 1;
      }
@@@ -1077,14 -1081,14 +1080,14 @@@ cgraph_turn_edge_to_speculative (struc
      {
        fprintf (dump_file, "Indirect call -> speculative call"
               " %s/%i => %s/%i\n",
-              xstrdup (cgraph_node_name (n)), n->symbol.order,
-              xstrdup (cgraph_node_name (n2)), n2->symbol.order);
+              xstrdup (cgraph_node_name (n)), n->order,
+              xstrdup (cgraph_node_name (n2)), n2->order);
      }
    e->speculative = true;
    e2 = cgraph_create_edge (n, n2, e->call_stmt, direct_count, direct_frequency);
    initialize_inline_failed (e2);
    e2->speculative = true;
-   if (TREE_NOTHROW (n2->symbol.decl))
+   if (TREE_NOTHROW (n2->decl))
      e2->can_throw_external = false;
    else
      e2->can_throw_external = e->can_throw_external;
    e->count -= e2->count;
    e->frequency -= e2->frequency;
    cgraph_call_edge_duplication_hooks (e, e2);
-   ref = ipa_record_reference ((symtab_node)n, (symtab_node)n2,
+   ref = ipa_record_reference (n, n2,
                              IPA_REF_ADDR, e->call_stmt);
    ref->lto_stmt_uid = e->lto_stmt_uid;
    ref->speculative = e->speculative;
@@@ -1146,7 -1150,7 +1149,7 @@@ cgraph_speculative_call_info (struct cg
    indirect = e2;
  
    reference = NULL;
-   for (i = 0; ipa_ref_list_reference_iterate (&e->caller->symbol.ref_list,
+   for (i = 0; ipa_ref_list_reference_iterate (&e->caller->ref_list,
                                              i, ref); i++)
      if (ref->speculative
        && ((ref->stmt && ref->stmt == e->call_stmt)
@@@ -1188,7 -1192,7 +1191,7 @@@ cgraph_resolve_speculation (struct cgra
    gcc_assert (edge->speculative);
    cgraph_speculative_call_info (edge, e2, edge, ref);
    if (!callee_decl
-       || !symtab_semantically_equivalent_p ((symtab_node) ref->referred,
+       || !symtab_semantically_equivalent_p (ref->referred,
                                            symtab_get_node (callee_decl)))
      {
        if (dump_file)
            {
              fprintf (dump_file, "Speculative indirect call %s/%i => %s/%i has "
                       "turned out to have contradicting known target ",
-                      xstrdup (cgraph_node_name (edge->caller)), edge->caller->symbol.order,
-                      xstrdup (cgraph_node_name (e2->callee)), e2->callee->symbol.order);
+                      xstrdup (cgraph_node_name (edge->caller)), edge->caller->order,
+                      xstrdup (cgraph_node_name (e2->callee)), e2->callee->order);
              print_generic_expr (dump_file, callee_decl, 0);
              fprintf (dump_file, "\n");
            }
          else
            {
              fprintf (dump_file, "Removing speculative call %s/%i => %s/%i\n",
-                      xstrdup (cgraph_node_name (edge->caller)), edge->caller->symbol.order,
-                      xstrdup (cgraph_node_name (e2->callee)), e2->callee->symbol.order);
+                      xstrdup (cgraph_node_name (edge->caller)), edge->caller->order,
+                      xstrdup (cgraph_node_name (e2->callee)), e2->callee->order);
            }
        }
      }
@@@ -1248,7 -1252,7 +1251,7 @@@ cgraph_make_edge_direct (struct cgraph_
    /* If we are redirecting speculative call, make it non-speculative.  */
    if (edge->indirect_unknown_callee && edge->speculative)
      {
-       edge = cgraph_resolve_speculation (edge, callee->symbol.decl);
+       edge = cgraph_resolve_speculation (edge, callee->decl);
  
        /* On successful speculation just return the pre existing direct edge.  */
        if (!edge->indirect_unknown_callee)
  
    if (edge->call_stmt)
      edge->call_stmt_cannot_inline_p
-       = !gimple_check_call_matching_types (edge->call_stmt, callee->symbol.decl,
+       = !gimple_check_call_matching_types (edge->call_stmt, callee->decl,
                                           false);
  
    /* We need to re-determine the inlining status of the edge.  */
@@@ -1316,23 -1320,23 +1319,23 @@@ cgraph_redirect_edge_call_stmt_to_calle
         signature.  We did not update the call statement yet, so compare it 
         with the reference that still points to the proper type.  */
        else if (!gimple_check_call_matching_types (e->call_stmt,
-                                                 ref->referred->symbol.decl,
+                                                 ref->referred->decl,
                                                  true))
        {
          if (dump_file)
            fprintf (dump_file, "Not expanding speculative call of %s/%i -> %s/%i\n"
                     "Type mismatch.\n",
                     xstrdup (cgraph_node_name (e->caller)),
-                    e->caller->symbol.order,
+                    e->caller->order,
                     xstrdup (cgraph_node_name (e->callee)),
-                    e->callee->symbol.order);
+                    e->callee->order);
          e = cgraph_resolve_speculation (e, NULL);
          /* We are producing the final function body and will throw away the
             callgraph edges really soon.  Reset the counts/frequencies to
             keep verifier happy in the case of roundoff errors.  */
          e->count = gimple_bb (e->call_stmt)->count;
          e->frequency = compute_call_stmt_bb_frequency
-                         (e->caller->symbol.decl, gimple_bb (e->call_stmt));
+                         (e->caller->decl, gimple_bb (e->call_stmt));
        }
        /* Expand speculation into GIMPLE code.  */
        else
                     "Expanding speculative call of %s/%i -> %s/%i count:"
                     HOST_WIDEST_INT_PRINT_DEC"\n",
                     xstrdup (cgraph_node_name (e->caller)),
-                    e->caller->symbol.order,
+                    e->caller->order,
                     xstrdup (cgraph_node_name (e->callee)),
-                    e->callee->symbol.order,
+                    e->callee->order,
                     (HOST_WIDEST_INT)e->count);
          gcc_assert (e2->speculative);
-         push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl));
+         push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
          new_stmt = gimple_ic (e->call_stmt, cgraph (ref->referred),
                                e->count || e2->count
                                ?  RDIV (e->count * REG_BR_PROB_BASE,
          cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt,
                                                 new_stmt, false);
          e->frequency = compute_call_stmt_bb_frequency
-                          (e->caller->symbol.decl, gimple_bb (e->call_stmt));
+                          (e->caller->decl, gimple_bb (e->call_stmt));
          e2->frequency = compute_call_stmt_bb_frequency
-                          (e2->caller->symbol.decl, gimple_bb (e2->call_stmt));
+                          (e2->caller->decl, gimple_bb (e2->call_stmt));
          e2->speculative = false;
          ref->speculative = false;
          ref->stmt = NULL;
      }
  
    if (e->indirect_unknown_callee
-       || decl == e->callee->symbol.decl)
+       || decl == e->callee->decl)
      return e->call_stmt;
  
  #ifdef ENABLE_CHECKING
    if (cgraph_dump_file)
      {
        fprintf (cgraph_dump_file, "updating call of %s/%i -> %s/%i: ",
-              xstrdup (cgraph_node_name (e->caller)), e->caller->symbol.order,
-              xstrdup (cgraph_node_name (e->callee)), e->callee->symbol.order);
+              xstrdup (cgraph_node_name (e->caller)), e->caller->order,
+              xstrdup (cgraph_node_name (e->callee)), e->callee->order);
        print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
        if (e->callee->clone.combined_args_to_skip)
        {
        new_stmt
        = gimple_call_copy_skip_args (e->call_stmt,
                                      e->callee->clone.combined_args_to_skip);
-       gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl);
+       gimple_call_set_fndecl (new_stmt, e->callee->decl);
        gimple_call_set_fntype (new_stmt, gimple_call_fntype (e->call_stmt));
  
        if (gimple_vdef (new_stmt)
    else
      {
        new_stmt = e->call_stmt;
-       gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl);
+       gimple_call_set_fndecl (new_stmt, e->callee->decl);
        update_stmt (new_stmt);
      }
  
@@@ -1482,7 -1486,7 +1485,7 @@@ cgraph_update_edges_for_call_stmt_node 
              struct cgraph_node *callee = e->callee;
              while (callee)
                {
-                 if (callee->symbol.decl == new_call
+                 if (callee->decl == new_call
                      || callee->former_clone_of == new_call)
                    return;
                  callee = callee->clone_of;
@@@ -1655,17 -1659,17 +1658,17 @@@ cgraph_release_function_body (struct cg
    node->ipa_transforms_to_apply.release ();
    if (!node->used_as_abstract_origin && cgraph_state != CGRAPH_STATE_PARSING)
      {
-       DECL_RESULT (node->symbol.decl) = NULL;
-       DECL_ARGUMENTS (node->symbol.decl) = NULL;
+       DECL_RESULT (node->decl) = NULL;
+       DECL_ARGUMENTS (node->decl) = NULL;
      }
    /* If the node is abstract and needed, then do not clear DECL_INITIAL
       of its associated function function declaration because it's
       needed to emit debug info later.  */
-   if (!node->used_as_abstract_origin && DECL_INITIAL (node->symbol.decl))
-     DECL_INITIAL (node->symbol.decl) = error_mark_node;
-   release_function_body (node->symbol.decl);
-   if (node->symbol.lto_file_data)
-     lto_free_function_in_decl_state_for_node ((symtab_node) node);
+   if (!node->used_as_abstract_origin && DECL_INITIAL (node->decl))
+     DECL_INITIAL (node->decl) = error_mark_node;
+   release_function_body (node->decl);
+   if (node->lto_file_data)
+     lto_free_function_in_decl_state_for_node (node);
  }
  
  /* Remove the node from cgraph.  */
@@@ -1683,8 -1687,8 +1686,8 @@@ cgraph_remove_node (struct cgraph_node 
  
    /* Incremental inlining access removed nodes stored in the postorder list.
       */
-   node->symbol.force_output = false;
-   node->symbol.forced_by_abi = false;
+   node->force_output = false;
+   node->forced_by_abi = false;
    for (n = node->nested; n; n = n->next_nested)
      n->origin = NULL;
    node->nested = NULL;
        node2 = &(*node2)->next_nested;
        *node2 = node->next_nested;
      }
-   symtab_unregister_node ((symtab_node)node);
+   symtab_unregister_node (node);
    if (node->prev_sibling_clone)
      node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
    else if (node->clone_of)
       */
    if (cgraph_state != CGRAPH_LTO_STREAMING)
      {
-       n = cgraph_get_node (node->symbol.decl);
+       n = cgraph_get_node (node->decl);
        if (!n
          || (!n->clones && !n->clone_of && !n->global.inlined_to
              && (cgraph_global_info_ready
-                 && (TREE_ASM_WRITTEN (n->symbol.decl)
-                     || DECL_EXTERNAL (n->symbol.decl)
-                     || !n->symbol.analyzed
-                     || (!flag_wpa && n->symbol.in_other_partition)))))
+                 && (TREE_ASM_WRITTEN (n->decl)
+                     || DECL_EXTERNAL (n->decl)
+                     || !n->analyzed
+                     || (!flag_wpa && n->in_other_partition)))))
        cgraph_release_function_body (node);
      }
  
-   node->symbol.decl = NULL;
+   node->decl = NULL;
    if (node->call_site_hash)
      {
        htab_delete (node->call_site_hash);
    /* Clear out the node to NULL all pointers and add the node to the free
       list.  */
    memset (node, 0, sizeof (*node));
-   node->symbol.type = SYMTAB_FUNCTION;
+   node->type = SYMTAB_FUNCTION;
    node->uid = uid;
    SET_NEXT_FREE_NODE (node, free_nodes);
    free_nodes = node;
@@@ -1787,9 -1791,9 +1790,9 @@@ cgraph_mark_address_taken_node (struct 
       of the object was taken (and thus it should be set on node alias is
       referring to).  We should remove the first use and the remove the
       following set.  */
-   node->symbol.address_taken = 1;
+   node->address_taken = 1;
    node = cgraph_function_or_thunk_node (node, NULL);
-   node->symbol.address_taken = 1;
+   node->address_taken = 1;
  }
  
  /* Return local info for the compiled function.  */
@@@ -1831,7 -1835,7 +1834,7 @@@ cgraph_rtl_info (tree decl
    node = cgraph_get_node (decl);
    if (!node
        || (decl != current_function_decl
-         && !TREE_ASM_WRITTEN (node->symbol.decl)))
+         && !TREE_ASM_WRITTEN (node->decl)))
      return NULL;
    return &node->rtl;
  }
@@@ -1867,18 -1871,18 +1870,18 @@@ dump_cgraph_node (FILE *f, struct cgrap
    struct cgraph_edge *edge;
    int indirect_calls_count = 0;
  
-   dump_symtab_base (f, (symtab_node) node);
+   dump_symtab_base (f, node);
  
    if (node->global.inlined_to)
      fprintf (f, "  Function %s/%i is inline copy in %s/%i\n",
             xstrdup (cgraph_node_name (node)),
-            node->symbol.order,
+            node->order,
             xstrdup (cgraph_node_name (node->global.inlined_to)),
-            node->global.inlined_to->symbol.order);
+            node->global.inlined_to->order);
    if (node->clone_of)
      fprintf (f, "  Clone of %s/%i\n",
             cgraph_node_asm_name (node->clone_of),
-            node->clone_of->symbol.order);
+            node->clone_of->order);
    if (cgraph_function_flags_ready)
      fprintf (f, "  Availability: %s\n",
             cgraph_availability_names [cgraph_function_body_availability (node)]);
             (HOST_WIDEST_INT)node->count);
    if (node->origin)
      fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin));
-   if (gimple_has_body_p (node->symbol.decl))
+   if (gimple_has_body_p (node->decl))
      fprintf (f, " body");
    if (node->process)
      fprintf (f, " process");
               (int)node->thunk.virtual_value,
               (int)node->thunk.virtual_offset_p);
      }
-   if (node->symbol.alias && node->thunk.alias
+   if (node->alias && node->thunk.alias
        && DECL_P (node->thunk.alias))
      {
        fprintf (f, "  Alias of %s",
    for (edge = node->callers; edge; edge = edge->next_caller)
      {
        fprintf (f, "%s/%i ", cgraph_node_asm_name (edge->caller),
-              edge->caller->symbol.order);
+              edge->caller->order);
        if (edge->count)
        fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
                 (HOST_WIDEST_INT)edge->count);
    for (edge = node->callees; edge; edge = edge->next_callee)
      {
        fprintf (f, "%s/%i ", cgraph_node_asm_name (edge->callee),
-              edge->callee->symbol.order);
+              edge->callee->order);
        if (edge->speculative)
        fprintf (f, "(speculative) ");
        if (!edge->inline_failed)
@@@ -2043,20 -2047,20 +2046,20 @@@ enum availabilit
  cgraph_function_body_availability (struct cgraph_node *node)
  {
    enum availability avail;
-   if (!node->symbol.analyzed)
+   if (!node->analyzed)
      avail = AVAIL_NOT_AVAILABLE;
    else if (node->local.local)
      avail = AVAIL_LOCAL;
-   else if (node->symbol.alias && node->symbol.weakref)
+   else if (node->alias && node->weakref)
      cgraph_function_or_thunk_node (node, &avail);
-   else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (node->symbol.decl)))
+   else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (node->decl)))
      avail = AVAIL_OVERWRITABLE;
-   else if (!node->symbol.externally_visible)
+   else if (!node->externally_visible)
      avail = AVAIL_AVAILABLE;
    /* Inline functions are safe to be analyzed even if their symbol can
       be overwritten at runtime.  It is not meaningful to enforce any sane
       behaviour on replacing inline function by different body.  */
-   else if (DECL_DECLARED_INLINE_P (node->symbol.decl))
+   else if (DECL_DECLARED_INLINE_P (node->decl))
      avail = AVAIL_AVAILABLE;
  
    /* If the function can be overwritten, return OVERWRITABLE.  Take
       AVAIL_AVAILABLE here?  That would be good reason to preserve this
       bit.  */
  
-   else if (decl_replaceable_p (node->symbol.decl)
-          && !DECL_EXTERNAL (node->symbol.decl))
+   else if (decl_replaceable_p (node->decl)
+          && !DECL_EXTERNAL (node->decl))
      avail = AVAIL_OVERWRITABLE;
    else avail = AVAIL_AVAILABLE;
  
@@@ -2082,12 -2086,12 +2085,12 @@@ static boo
  cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node,
                                 void *data ATTRIBUTE_UNUSED)
  {
-   return !(!node->symbol.force_output
-          && ((DECL_COMDAT (node->symbol.decl)
-               && !node->symbol.forced_by_abi
-               && !symtab_used_from_object_file_p ((symtab_node) node)
-               && !node->symbol.same_comdat_group)
-              || !node->symbol.externally_visible));
+   return !(!node->force_output
+          && ((DECL_COMDAT (node->decl)
+               && !node->forced_by_abi
+               && !symtab_used_from_object_file_p (node)
+               && !node->same_comdat_group)
+              || !node->externally_visible));
  }
  
  /* Return true if NODE can be made local for API change.
  bool
  cgraph_node_can_be_local_p (struct cgraph_node *node)
  {
-   return (!node->symbol.address_taken
+   return (!node->address_taken
          && !cgraph_for_node_and_aliases (node,
                                           cgraph_node_cannot_be_local_p_1,
                                           NULL, true));
@@@ -2126,7 -2130,7 +2129,7 @@@ cgraph_for_node_thunks_and_aliases (str
        if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data,
                                              include_overwritable))
        return true;
-   for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++)
+   for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
      if (ref->use == IPA_REF_ALIAS)
        {
        struct cgraph_node *alias = ipa_ref_referring_node (ref);
@@@ -2154,7 -2158,7 +2157,7 @@@ cgraph_for_node_and_aliases (struct cgr
  
    if (callback (node, data))
      return true;
-   for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++)
+   for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
      if (ref->use == IPA_REF_ALIAS)
        {
        struct cgraph_node *alias = ipa_ref_referring_node (ref);
@@@ -2173,16 -2177,16 +2176,16 @@@ static boo
  cgraph_make_node_local_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
  {
    gcc_checking_assert (cgraph_node_can_be_local_p (node));
-   if (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
+   if (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
      {
-       symtab_make_decl_local (node->symbol.decl);
+       symtab_make_decl_local (node->decl);
  
-       node->symbol.externally_visible = false;
-       node->symbol.forced_by_abi = false;
+       node->externally_visible = false;
+       node->forced_by_abi = false;
        node->local.local = true;
-       node->symbol.unique_name = (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
-                                 || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
-       node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
+       node->unique_name = (node->resolution == LDPR_PREVAILING_DEF_IRONLY
+                                 || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
+       node->resolution = LDPR_PREVAILING_DEF_IRONLY;
        gcc_assert (cgraph_function_body_availability (node) == AVAIL_LOCAL);
      }
    return false;
@@@ -2204,7 -2208,7 +2207,7 @@@ cgraph_set_nothrow_flag_1 (struct cgrap
  {
    struct cgraph_edge *e;
  
-   TREE_NOTHROW (node->symbol.decl) = data != NULL;
+   TREE_NOTHROW (node->decl) = data != NULL;
  
    if (data != NULL)
      for (e = node->callers; e; e = e->next_caller)
@@@ -2231,13 -2235,13 +2234,13 @@@ cgraph_set_const_flag_1 (struct cgraph_
       optimized out.  */
    if (data && !((size_t)data & 2))
      {
-       if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
-       DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
-       if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
-       DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
+       if (DECL_STATIC_CONSTRUCTOR (node->decl))
+       DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
+       if (DECL_STATIC_DESTRUCTOR (node->decl))
+       DECL_STATIC_DESTRUCTOR (node->decl) = 0;
      }
-   TREE_READONLY (node->symbol.decl) = data != NULL;
-   DECL_LOOPING_CONST_OR_PURE_P (node->symbol.decl) = ((size_t)data & 2) != 0;
+   TREE_READONLY (node->decl) = data != NULL;
+   DECL_LOOPING_CONST_OR_PURE_P (node->decl) = ((size_t)data & 2) != 0;
    return false;
  }
  
@@@ -2261,13 -2265,13 +2264,13 @@@ cgraph_set_pure_flag_1 (struct cgraph_n
       optimized out.  */
    if (data && !((size_t)data & 2))
      {
-       if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
-       DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
-       if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
-       DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
+       if (DECL_STATIC_CONSTRUCTOR (node->decl))
+       DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
+       if (DECL_STATIC_DESTRUCTOR (node->decl))
+       DECL_STATIC_DESTRUCTOR (node->decl) = 0;
      }
-   DECL_PURE_P (node->symbol.decl) = data != NULL;
-   DECL_LOOPING_CONST_OR_PURE_P (node->symbol.decl) = ((size_t)data & 2) != 0;
+   DECL_PURE_P (node->decl) = data != NULL;
+   DECL_LOOPING_CONST_OR_PURE_P (node->decl) = ((size_t)data & 2) != 0;
    return false;
  }
  
@@@ -2288,7 -2292,7 +2291,7 @@@ cgraph_set_pure_flag (struct cgraph_nod
  bool
  cgraph_node_cannot_return (struct cgraph_node *node)
  {
-   int flags = flags_from_decl_or_type (node->symbol.decl);
+   int flags = flags_from_decl_or_type (node->decl);
    if (!flag_exceptions)
      return (flags & ECF_NORETURN) != 0;
    else
@@@ -2327,19 -2331,19 +2330,19 @@@ cgraph_can_remove_if_no_direct_calls_an
  {
    gcc_assert (!node->global.inlined_to);
    /* Extern inlines can always go, we will use the external definition.  */
-   if (DECL_EXTERNAL (node->symbol.decl))
+   if (DECL_EXTERNAL (node->decl))
      return true;
    /* When function is needed, we can not remove it.  */
-   if (node->symbol.force_output || node->symbol.used_from_other_partition)
+   if (node->force_output || node->used_from_other_partition)
      return false;
-   if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
-       || DECL_STATIC_DESTRUCTOR (node->symbol.decl))
+   if (DECL_STATIC_CONSTRUCTOR (node->decl)
+       || DECL_STATIC_DESTRUCTOR (node->decl))
      return false;
    /* Only COMDAT functions can be removed if externally visible.  */
-   if (node->symbol.externally_visible
-       && (!DECL_COMDAT (node->symbol.decl)
-         || node->symbol.forced_by_abi
-         || symtab_used_from_object_file_p ((symtab_node) node)))
+   if (node->externally_visible
+       && (!DECL_COMDAT (node->decl)
+         || node->forced_by_abi
+         || symtab_used_from_object_file_p (node)))
      return false;
    return true;
  }
@@@ -2359,9 -2363,9 +2362,9 @@@ boo
  cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
  {
    /* Extern inlines can always go, we will use the external definition.  */
-   if (DECL_EXTERNAL (node->symbol.decl))
+   if (DECL_EXTERNAL (node->decl))
      return true;
-   if (node->symbol.address_taken)
+   if (node->address_taken)
      return false;
    return !cgraph_for_node_and_aliases (node, nonremovable_p, NULL, true);
  }
  static bool
  used_from_object_file_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
  {
-   return symtab_used_from_object_file_p ((symtab_node) node);
+   return symtab_used_from_object_file_p (node);
  }
  
  /* Return true when function NODE can be expected to be removed
@@@ -2398,7 -2402,7 +2401,7 @@@ cgraph_will_be_removed_from_program_if_
      return cgraph_only_called_directly_p (node);
    else
      {
-        if (DECL_EXTERNAL (node->symbol.decl))
+        if (DECL_EXTERNAL (node->decl))
           return true;
        return cgraph_can_remove_if_no_direct_calls_p (node);
      }
@@@ -2488,7 -2492,7 +2491,7 @@@ verify_edge_count_and_frequency (struc
        error ("caller edge frequency is too large");
        error_found = true;
      }
-   if (gimple_has_body_p (e->caller->symbol.decl)
+   if (gimple_has_body_p (e->caller->decl)
        && !e->caller->global.inlined_to
        && !e->speculative
        /* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out.
              && ((inline_edge_summary_vec.length () <= (unsigned) e->uid)
                  || !inline_edge_summary (e)->predicate)))
        && (e->frequency
-         != compute_call_stmt_bb_frequency (e->caller->symbol.decl,
+         != compute_call_stmt_bb_frequency (e->caller->decl,
                                             gimple_bb (e->call_stmt))))
      {
        error ("caller edge frequency %i does not match BB frequency %i",
             e->frequency,
-            compute_call_stmt_bb_frequency (e->caller->symbol.decl,
+            compute_call_stmt_bb_frequency (e->caller->decl,
                                             gimple_bb (e->call_stmt)));
        error_found = true;
      }
@@@ -2545,11 -2549,11 +2548,11 @@@ verify_edge_corresponds_to_fndecl (stru
  
    /* We do not know if a node from a different partition is an alias or what it
       aliases and therefore cannot do the former_clone_of check reliably.  */
-   if (!node || node->symbol.in_other_partition || e->callee->symbol.in_other_partition)
+   if (!node || node->in_other_partition || e->callee->in_other_partition)
      return false;
    node = cgraph_function_or_thunk_node (node, NULL);
  
-   if (e->callee->former_clone_of != node->symbol.decl
+   if (e->callee->former_clone_of != node->decl
        /* IPA-CP sometimes redirect edge to clone and then back to the former
         function.  This ping-pong has to go, eventually.  */
        && (node != cgraph_function_or_thunk_node (e->callee, NULL))
@@@ -2564,7 -2568,7 +2567,7 @@@ DEBUG_FUNCTION voi
  verify_cgraph_node (struct cgraph_node *node)
  {
    struct cgraph_edge *e;
-   struct function *this_cfun = DECL_STRUCT_FUNCTION (node->symbol.decl);
+   struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl);
    basic_block this_block;
    gimple_stmt_iterator gsi;
    bool error_found = false;
      return;
  
    timevar_push (TV_CGRAPH_VERIFY);
-   error_found |= verify_symtab_base ((symtab_node) node);
+   error_found |= verify_symtab_base (node);
    for (e = node->callees; e; e = e->next_callee)
      if (e->aux)
        {
        error ("execution count is negative");
        error_found = true;
      }
-   if (node->global.inlined_to && node->symbol.same_comdat_group)
+   if (node->global.inlined_to && node->same_comdat_group)
      {
        error ("inline clone in same comdat group list");
        error_found = true;
      }
-   if (!node->symbol.definition && !node->symbol.in_other_partition && node->local.local)
+   if (!node->definition && !node->in_other_partition && node->local.local)
      {
        error ("local symbols must be defined");
        error_found = true;
      }
-   if (node->global.inlined_to && node->symbol.externally_visible)
+   if (node->global.inlined_to && node->externally_visible)
      {
        error ("externally visible inline clone");
        error_found = true;
      }
-   if (node->global.inlined_to && node->symbol.address_taken)
+   if (node->global.inlined_to && node->address_taken)
      {
        error ("inline clone with address taken");
        error_found = true;
      }
-   if (node->global.inlined_to && node->symbol.force_output)
+   if (node->global.inlined_to && node->force_output)
      {
        error ("inline clone is forced to output");
        error_found = true;
        error_found = true;
      }
  
-   if (node->symbol.analyzed && node->symbol.alias)
+   if (node->analyzed && node->alias)
      {
        bool ref_found = false;
        int i;
          error ("Alias has call edges");
            error_found = true;
        }
-       for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list,
+       for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list,
                                                  i, ref); i++)
        if (ref->use != IPA_REF_ALIAS)
          {
            error_found = true;
          }
      }
-   if (node->symbol.analyzed && node->thunk.thunk_p)
+   if (node->analyzed && node->thunk.thunk_p)
      {
        if (!node->callees)
        {
          error ("More than one edge out of thunk node");
            error_found = true;
        }
-       if (gimple_has_body_p (node->symbol.decl))
+       if (gimple_has_body_p (node->decl))
          {
          error ("Thunk is not supposed to have body");
            error_found = true;
          }
      }
-   else if (node->symbol.analyzed && gimple_has_body_p (node->symbol.decl)
-            && !TREE_ASM_WRITTEN (node->symbol.decl)
-            && (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to)
+   else if (node->analyzed && gimple_has_body_p (node->decl)
+            && !TREE_ASM_WRITTEN (node->decl)
+            && (!DECL_EXTERNAL (node->decl) || node->global.inlined_to)
             && !flag_wpa)
      {
        if (this_cfun->cfg)
                              if (verify_edge_corresponds_to_fndecl (e, decl))
                                {
                                  error ("edge points to wrong declaration:");
-                                 debug_tree (e->callee->symbol.decl);
+                                 debug_tree (e->callee->decl);
                                  fprintf (stderr," Instead of:");
                                  debug_tree (decl);
                                  error_found = true;
                }
              }
            for (i = 0;
-                ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref);
+                ipa_ref_list_reference_iterate (&node->ref_list, i, ref);
                 i++)
              if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
                {
@@@ -2915,17 -2919,17 +2918,17 @@@ cgraph_get_create_real_symbol_node (tre
      {
        first_clone->clone_of = node;
        node->clones = first_clone;
-       symtab_prevail_in_asm_name_hash ((symtab_node) node);
-       symtab_insert_node_to_hashtable ((symtab_node) node);
+       symtab_prevail_in_asm_name_hash (node);
+       symtab_insert_node_to_hashtable (node);
        if (dump_file)
        fprintf (dump_file, "Introduced new external node "
                 "(%s/%i) and turned into root of the clone tree.\n",
-                xstrdup (cgraph_node_name (node)), node->symbol.order);
+                xstrdup (cgraph_node_name (node)), node->order);
      }
    else if (dump_file)
      fprintf (dump_file, "Introduced new external node "
             "(%s/%i).\n", xstrdup (cgraph_node_name (node)),
-            node->symbol.order);
+            node->order);
    return node;
  }
  
@@@ -2964,14 -2968,14 +2967,14 @@@ cgraph_get_body (struct cgraph_node *no
    struct lto_file_decl_data *file_data;
    const char *data, *name;
    size_t len;
-   tree decl = node->symbol.decl;
+   tree decl = node->decl;
  
    if (DECL_RESULT (decl))
      return false;
  
    gcc_assert (in_lto_p);
  
-   file_data = node->symbol.lto_file_data;
+   file_data = node->lto_file_data;
    name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
  
    /* We may have renamed the declaration, e.g., a static function.  */
    lto_stats.num_function_bodies++;
    lto_free_section_data (file_data, LTO_section_function_body, name,
                         data, len);
-   lto_free_function_in_decl_state_for_node ((symtab_node) node);
+   lto_free_function_in_decl_state_for_node (node);
    return true;
  }
  
diff --combined gcc/cgraphunit.c
index 910d7978aea12cf6fdf95fbea0763c5a4007bb44,c3a8967e843af60f9508e8431c1ecb6493cfe1f4..4978d2aea1a5789969ff89cad4ab2fa9e0672bfd
@@@ -164,6 -164,10 +164,10 @@@ along with GCC; see the file COPYING3
  #include "tree.h"
  #include "output.h"
  #include "rtl.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-into-ssa.h"
  #include "tree-ssa.h"
  #include "tree-inline.h"
  #include "langhooks.h"
  #include "ggc.h"
  #include "debug.h"
  #include "target.h"
- #include "cgraph.h"
  #include "diagnostic.h"
  #include "params.h"
  #include "fibheap.h"
  #include "intl.h"
  #include "function.h"
  #include "ipa-prop.h"
- #include "gimple.h"
  #include "tree-iterator.h"
  #include "tree-pass.h"
  #include "tree-dump.h"
@@@ -223,27 -225,27 +225,27 @@@ static GTY (()) tree vtable_entry_type
     either outside this translation unit, something magic in the system
     configury */
  bool
- decide_is_symbol_needed (symtab_node node)
+ decide_is_symbol_needed (symtab_node *node)
  {
-   tree decl = node->symbol.decl;
+   tree decl = node->decl;
  
    /* Double check that no one output the function into assembly file
       early.  */
    gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
                       || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
  
-   if (!node->symbol.definition)
+   if (!node->definition)
      return false;
  
    if (DECL_EXTERNAL (decl))
      return false;
  
    /* If the user told us it is used, then it must be so.  */
-   if (node->symbol.force_output)
+   if (node->force_output)
      return true;
  
    /* ABI forced symbols are needed when they are external.  */
-   if (node->symbol.forced_by_abi && TREE_PUBLIC (decl))
+   if (node->forced_by_abi && TREE_PUBLIC (decl))
      return true;
  
   /* Keep constructors, destructors and virtual functions.  */
  
  /* Head of the queue of nodes to be processed while building callgraph */
  
- static symtab_node first = (symtab_node)(void *)1;
+ static symtab_node *first = (symtab_node *)(void *)1;
  
  /* Add NODE to queue starting at FIRST. 
     The queue is linked via AUX pointers and terminated by pointer to 1.  */
  
  static void
- enqueue_node (symtab_node node)
+ enqueue_node (symtab_node *node)
  {
-   if (node->symbol.aux)
+   if (node->aux)
      return;
    gcc_checking_assert (first);
-   node->symbol.aux = first;
+   node->aux = first;
    first = node;
  }
  
@@@ -296,7 -298,7 +298,7 @@@ cgraph_process_new_functions (void
    for (csi = csi_start (cgraph_new_nodes); !csi_end_p (csi); csi_next (&csi))
      {
        node = csi_node (csi);
-       fndecl = node->symbol.decl;
+       fndecl = node->decl;
        switch (cgraph_state)
        {
        case CGRAPH_STATE_CONSTRUCTION:
          cgraph_finalize_function (fndecl, false);
          output = true;
            cgraph_call_function_insertion_hooks (node);
-         enqueue_node ((symtab_node) node);
+         enqueue_node (node);
          break;
  
        case CGRAPH_STATE_IPA:
             cgraph but not on this function.  */
  
          gimple_register_cfg_hooks ();
-         if (!node->symbol.analyzed)
+         if (!node->analyzed)
            analyze_function (node);
          push_cfun (DECL_STRUCT_FUNCTION (fndecl));
          if (cgraph_state == CGRAPH_STATE_IPA_SSA
@@@ -372,25 -374,25 +374,25 @@@ cgraph_reset_node (struct cgraph_node *
    memset (&node->local, 0, sizeof (node->local));
    memset (&node->global, 0, sizeof (node->global));
    memset (&node->rtl, 0, sizeof (node->rtl));
-   node->symbol.analyzed = false;
-   node->symbol.definition = false;
-   node->symbol.alias = false;
-   node->symbol.weakref = false;
-   node->symbol.cpp_implicit_alias = false;
+   node->analyzed = false;
+   node->definition = false;
+   node->alias = false;
+   node->weakref = false;
+   node->cpp_implicit_alias = false;
  
    cgraph_node_remove_callees (node);
-   ipa_remove_all_references (&node->symbol.ref_list);
+   ipa_remove_all_references (&node->ref_list);
  }
  
  /* Return true when there are references to NODE.  */
  
  static bool
- referred_to_p (symtab_node node)
+ referred_to_p (symtab_node *node)
  {
    struct ipa_ref *ref;
  
    /* See if there are any references at all.  */
-   if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
+   if (ipa_ref_list_referring_iterate (&node->ref_list, 0, ref))
      return true;
    /* For functions check also calls.  */
    cgraph_node *cn = dyn_cast <cgraph_node> (node);
@@@ -409,7 -411,7 +411,7 @@@ cgraph_finalize_function (tree decl, bo
  {
    struct cgraph_node *node = cgraph_get_create_node (decl);
  
-   if (node->symbol.definition)
+   if (node->definition)
      {
        /* Nested functions should only be defined once.  */
        gcc_assert (!DECL_CONTEXT (decl)
      }
  
    notice_global_symbol (decl);
-   node->symbol.definition = true;
+   node->definition = true;
    node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
  
    /* With -fkeep-inline-functions we are keeping all inline functions except
        && DECL_DECLARED_INLINE_P (decl)
        && !DECL_EXTERNAL (decl)
        && !DECL_DISREGARD_INLINE_LIMITS (decl))
-     node->symbol.force_output = 1;
+     node->force_output = 1;
  
    /* When not optimizing, also output the static functions. (see
       PR24561), but don't do so for always_inline functions, functions
       in the original implementation and it is unclear whether we want
       to change the behavior here.  */
    if ((!optimize
-        && !node->symbol.cpp_implicit_alias
+        && !node->cpp_implicit_alias
         && !DECL_DISREGARD_INLINE_LIMITS (decl)
         && !DECL_DECLARED_INLINE_P (decl)
         && !(DECL_CONTEXT (decl)
            && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL))
        && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
-     node->symbol.force_output = 1;
+     node->force_output = 1;
  
    /* If we've not yet emitted decl, tell the debug info about it.  */
    if (!TREE_ASM_WRITTEN (decl))
      ggc_collect ();
  
    if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
-       && (decide_is_symbol_needed ((symtab_node) node)
-         || referred_to_p ((symtab_node)node)))
-     enqueue_node ((symtab_node)node);
+       && (decide_is_symbol_needed (node)
+         || referred_to_p (node)))
+     enqueue_node (node);
  }
  
  /* Add the function FNDECL to the call graph.
@@@ -500,8 -502,8 +502,8 @@@ cgraph_add_new_function (tree fndecl, b
           analyzing and compilation.  */
        node = cgraph_get_create_node (fndecl);
        node->local.local = false;
-       node->symbol.definition = true;
-       node->symbol.force_output = true;
+       node->definition = true;
+       node->force_output = true;
        if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
          {
            push_cfun (DECL_STRUCT_FUNCTION (fndecl));
        node = cgraph_create_node (fndecl);
        if (lowered)
          node->lowered = true;
-       node->symbol.definition = true;
+       node->definition = true;
        analyze_function (node);
        push_cfun (DECL_STRUCT_FUNCTION (fndecl));
        gimple_register_cfg_hooks ();
@@@ -588,7 -590,7 +590,7 @@@ output_asm_statements (void
  static void
  analyze_function (struct cgraph_node *node)
  {
-   tree decl = node->symbol.decl;
+   tree decl = node->decl;
    location_t saved_loc = input_location;
    input_location = DECL_SOURCE_LOCATION (decl);
  
        if (!expand_thunk (node, false))
        {
          node->thunk.alias = NULL;
-         node->symbol.analyzed = true;
+         node->analyzed = true;
          return;
        }
        node->thunk.alias = NULL;
      }
-   if (node->symbol.alias)
+   if (node->alias)
      symtab_resolve_alias
-        ((symtab_node) node, (symtab_node) cgraph_get_node (node->symbol.alias_target));
+        (node, cgraph_get_node (node->alias_target));
    else if (node->dispatcher_function)
      {
        /* Generate the dispatcher body of multi-versioned functions.  */
      {
        push_cfun (DECL_STRUCT_FUNCTION (decl));
  
-       assign_assembler_name_if_neeeded (node->symbol.decl);
+       assign_assembler_name_if_neeeded (node->decl);
  
        /* Make sure to gimplify bodies only once.  During analyzing a
         function we lower it, which will require gimplified nested
        if (!node->lowered)
        {
          if (node->nested)
-           lower_nested_functions (node->symbol.decl);
+           lower_nested_functions (node->decl);
          gcc_assert (!node->nested);
  
          gimple_register_cfg_hooks ();
  
        pop_cfun ();
      }
-   node->symbol.analyzed = true;
+   node->analyzed = true;
  
    input_location = saved_loc;
  }
  void
  cgraph_process_same_body_aliases (void)
  {
-   symtab_node node;
+   symtab_node *node;
    FOR_EACH_SYMBOL (node)
-     if (node->symbol.cpp_implicit_alias && !node->symbol.analyzed)
+     if (node->cpp_implicit_alias && !node->analyzed)
        symtab_resolve_alias
          (node,
-        TREE_CODE (node->symbol.alias_target) == VAR_DECL
-        ? (symtab_node)varpool_node_for_decl (node->symbol.alias_target)
-        : (symtab_node)cgraph_get_create_node (node->symbol.alias_target));
+        TREE_CODE (node->alias_target) == VAR_DECL
+        ? (symtab_node *)varpool_node_for_decl (node->alias_target)
+        : (symtab_node *)cgraph_get_create_node (node->alias_target));
    cpp_implicit_aliases_done = true;
  }
  
@@@ -732,20 -734,20 +734,20 @@@ process_function_and_variable_attribute
    for (node = cgraph_first_function (); node != first;
         node = cgraph_next_function (node))
      {
-       tree decl = node->symbol.decl;
+       tree decl = node->decl;
        if (DECL_PRESERVE_P (decl))
        cgraph_mark_force_output_node (node);
        else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
        {
-         if (! TREE_PUBLIC (node->symbol.decl))
-           warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
+         if (! TREE_PUBLIC (node->decl))
+           warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes,
                        "%<externally_visible%>"
                        " attribute have effect only on public objects");
        }
        if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
-         && (node->symbol.definition && !node->symbol.alias))
+         && (node->definition && !node->alias))
        {
-         warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
+         warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes,
                      "%<weakref%> attribute ignored"
                      " because function is defined");
          DECL_WEAK (decl) = 0;
    for (vnode = varpool_first_variable (); vnode != first_var;
         vnode = varpool_next_variable (vnode))
      {
-       tree decl = vnode->symbol.decl;
+       tree decl = vnode->decl;
        if (DECL_EXTERNAL (decl)
          && DECL_INITIAL (decl))
        varpool_finalize_decl (decl);
        if (DECL_PRESERVE_P (decl))
-       vnode->symbol.force_output = true;
+       vnode->force_output = true;
        else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
        {
-         if (! TREE_PUBLIC (vnode->symbol.decl))
-           warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
+         if (! TREE_PUBLIC (vnode->decl))
+           warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes,
                        "%<externally_visible%>"
                        " attribute have effect only on public objects");
        }
        if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
-         && vnode->symbol.definition
+         && vnode->definition
          && DECL_INITIAL (decl))
        {
-         warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
+         warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes,
                      "%<weakref%> attribute ignored"
                      " because variable is initialized");
          DECL_WEAK (decl) = 0;
@@@ -804,21 -806,21 +806,21 @@@ varpool_finalize_decl (tree decl
  
    gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
  
-   if (node->symbol.definition)
+   if (node->definition)
      return;
    notice_global_symbol (decl);
-   node->symbol.definition = true;
+   node->definition = true;
    if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
        /* Traditionally we do not eliminate static variables when not
         optimizing and when not doing toplevel reoder.  */
-       || (!flag_toplevel_reorder && !DECL_COMDAT (node->symbol.decl)
-         && !DECL_ARTIFICIAL (node->symbol.decl)))
-     node->symbol.force_output = true;
+       || (!flag_toplevel_reorder && !DECL_COMDAT (node->decl)
+         && !DECL_ARTIFICIAL (node->decl)))
+     node->force_output = true;
  
    if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
-       && (decide_is_symbol_needed ((symtab_node) node)
-         || referred_to_p ((symtab_node)node)))
-     enqueue_node ((symtab_node)node);
+       && (decide_is_symbol_needed (node)
+         || referred_to_p (node)))
+     enqueue_node (node);
    if (cgraph_state >= CGRAPH_STATE_IPA_SSA)
      varpool_analyze_node (node);
    /* Some frontends produce various interface variables after compilation
@@@ -855,14 -857,14 +857,14 @@@ walk_polymorphic_call_targets (pointer_
          /* Do not bother to mark virtual methods in anonymous namespace;
             either we will find use of virtual table defining it, or it is
             unused.  */
-         if (targets[i]->symbol.definition
+         if (targets[i]->definition
              && TREE_CODE
-                 (TREE_TYPE (targets[i]->symbol.decl))
+                 (TREE_TYPE (targets[i]->decl))
                   == METHOD_TYPE
              && !type_in_anonymous_namespace_p
                   (method_class_type
-                    (TREE_TYPE (targets[i]->symbol.decl))))
-         enqueue_node ((symtab_node) targets[i]);
+                    (TREE_TYPE (targets[i]->decl))))
+         enqueue_node (targets[i]);
        }
      }
  
@@@ -918,7 -920,8 +920,8 @@@ analyze_functions (void
    struct varpool_node *first_handled_var = first_analyzed_var;
    struct pointer_set_t *reachable_call_targets = pointer_set_create ();
  
-   symtab_node node, next;
+   symtab_node *node;
+   symtab_node *next;
    int i;
    struct ipa_ref *ref;
    bool changed = true;
       C++ FE is confused about the COMDAT groups being right.  */
    if (cpp_implicit_aliases_done)
      FOR_EACH_SYMBOL (node)
-       if (node->symbol.cpp_implicit_alias)
+       if (node->cpp_implicit_alias)
          fixup_same_cpp_alias_visibility (node, symtab_alias_target (node));
    if (optimize && flag_devirtualize)
      build_type_inheritance_graph ();
  
        /* First identify the trivially needed symbols.  */
        for (node = symtab_nodes;
-          node != (symtab_node)first_analyzed
-          && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
+          node != first_analyzed
+          && node != first_analyzed_var; node = node->next)
        {
          if (decide_is_symbol_needed (node))
            {
              if (!changed && cgraph_dump_file)
                fprintf (cgraph_dump_file, "\n");
            }
-         if (node == (symtab_node)first_analyzed
-             || node == (symtab_node)first_analyzed_var)
+         if (node == first_analyzed
+             || node == first_analyzed_var)
            break;
        }
        cgraph_process_new_functions ();
  
        /* Lower representation, build callgraph edges and references for all trivially
           needed symbols and all symbols referred by them.  */
-       while (first != (symtab_node)(void *)1)
+       while (first != (symtab_node *)(void *)1)
        {
          changed = true;
          node = first;
-         first = (symtab_node)first->symbol.aux;
+         first = (symtab_node *)first->aux;
          cgraph_node *cnode = dyn_cast <cgraph_node> (node);
-         if (cnode && cnode->symbol.definition)
+         if (cnode && cnode->definition)
            {
              struct cgraph_edge *edge;
-             tree decl = cnode->symbol.decl;
+             tree decl = cnode->decl;
  
              /* ??? It is possible to create extern inline function
              and later using weak alias attribute to kill its body.
              See gcc.c-torture/compile/20011119-1.c  */
              if (!DECL_STRUCT_FUNCTION (decl)
-                 && !cnode->symbol.alias
+                 && !cnode->alias
                  && !cnode->thunk.thunk_p
                  && !cnode->dispatcher_function)
                {
                  continue;
                }
  
-             if (!cnode->symbol.analyzed)
+             if (!cnode->analyzed)
                analyze_function (cnode);
  
              for (edge = cnode->callees; edge; edge = edge->next_callee)
-               if (edge->callee->symbol.definition)
-                  enqueue_node ((symtab_node)edge->callee);
+               if (edge->callee->definition)
+                  enqueue_node (edge->callee);
              if (optimize && flag_devirtualize)
                {
                  struct cgraph_edge *next;
          else
            {
              varpool_node *vnode = dyn_cast <varpool_node> (node);
-             if (vnode && vnode->symbol.definition && !vnode->symbol.analyzed)
+             if (vnode && vnode->definition && !vnode->analyzed)
                varpool_analyze_node (vnode);
            }
  
-         if (node->symbol.same_comdat_group)
+         if (node->same_comdat_group)
            {
-             symtab_node next;
-             for (next = node->symbol.same_comdat_group;
+             symtab_node *next;
+             for (next = node->same_comdat_group;
                   next != node;
-                  next = next->symbol.same_comdat_group)
+                  next = next->same_comdat_group)
                enqueue_node (next);
            }
-         for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
-           if (ref->referred->symbol.definition)
+         for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
+           if (ref->referred->definition)
              enqueue_node (ref->referred);
            cgraph_process_new_functions ();
        }
      fprintf (cgraph_dump_file, "\nRemoving unused symbols:");
  
    for (node = symtab_nodes;
-        node != (symtab_node)first_handled
-        && node != (symtab_node)first_handled_var; node = next)
+        node != first_handled
+        && node != first_handled_var; node = next)
      {
-       next = node->symbol.next;
-       if (!node->symbol.aux && !referred_to_p (node))
+       next = node->next;
+       if (!node->aux && !referred_to_p (node))
        {
          if (cgraph_dump_file)
            fprintf (cgraph_dump_file, " %s", symtab_node_name (node));
        }
        if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
        {
-         tree decl = node->symbol.decl;
+         tree decl = node->decl;
  
-         if (cnode->symbol.definition && !gimple_has_body_p (decl)
-             && !cnode->symbol.alias
+         if (cnode->definition && !gimple_has_body_p (decl)
+             && !cnode->alias
              && !cnode->thunk.thunk_p)
            cgraph_reset_node (cnode);
  
-         gcc_assert (!cnode->symbol.definition || cnode->thunk.thunk_p
-                     || cnode->symbol.alias
+         gcc_assert (!cnode->definition || cnode->thunk.thunk_p
+                     || cnode->alias
                      || gimple_has_body_p (decl));
-         gcc_assert (cnode->symbol.analyzed == cnode->symbol.definition);
+         gcc_assert (cnode->analyzed == cnode->definition);
        }
-       node->symbol.aux = NULL;
+       node->aux = NULL;
      }
-   for (;node; node = node->symbol.next)
-     node->symbol.aux = NULL;
+   for (;node; node = node->next)
+     node->aux = NULL;
    first_analyzed = cgraph_first_function ();
    first_analyzed_var = varpool_first_variable ();
    if (cgraph_dump_file)
@@@ -1123,7 -1126,7 +1126,7 @@@ handle_alias_pairs (void
    
    for (i = 0; alias_pairs && alias_pairs->iterate (i, &p);)
      {
-       symtab_node target_node = symtab_node_for_asm (p->target);
+       symtab_node *target_node = symtab_node_for_asm (p->target);
  
        /* Weakrefs with target not defined in current unit are easy to handle:
         they behave just as external variables except we need to note the
        if (!target_node
          && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL)
        {
-         symtab_node node = symtab_get_node (p->decl);
+         symtab_node *node = symtab_get_node (p->decl);
          if (node)
            {
-             node->symbol.alias_target = p->target;
-             node->symbol.weakref = true;
-             node->symbol.alias = true;
+             node->alias_target = p->target;
+             node->weakref = true;
+             node->alias = true;
            }
          alias_pairs->unordered_remove (i);
          continue;
        else if (!target_node)
        {
          error ("%q+D aliased to undefined symbol %qE", p->decl, p->target);
-         symtab_node node = symtab_get_node (p->decl);
+         symtab_node *node = symtab_get_node (p->decl);
          if (node)
-           node->symbol.alias = false;
+           node->alias = false;
          alias_pairs->unordered_remove (i);
          continue;
        }
  
-       if (DECL_EXTERNAL (target_node->symbol.decl)
+       if (DECL_EXTERNAL (target_node->decl)
          /* We use local aliases for C++ thunks to force the tailcall
             to bind locally.  This is a hack - to keep it working do
             the following (which is not strictly correct).  */
-         && (! TREE_CODE (target_node->symbol.decl) == FUNCTION_DECL
-             || ! DECL_VIRTUAL_P (target_node->symbol.decl))
+         && (! TREE_CODE (target_node->decl) == FUNCTION_DECL
+             || ! DECL_VIRTUAL_P (target_node->decl))
          && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
        {
          error ("%q+D aliased to external symbol %qE",
            && target_node && is_a <cgraph_node> (target_node))
        {
          struct cgraph_node *src_node = cgraph_get_node (p->decl);
-         if (src_node && src_node->symbol.definition)
+         if (src_node && src_node->definition)
              cgraph_reset_node (src_node);
-         cgraph_create_function_alias (p->decl, target_node->symbol.decl);
+         cgraph_create_function_alias (p->decl, target_node->decl);
          alias_pairs->unordered_remove (i);
        }
        else if (TREE_CODE (p->decl) == VAR_DECL
               && target_node && is_a <varpool_node> (target_node))
        {
-         varpool_create_variable_alias (p->decl, target_node->symbol.decl);
+         varpool_create_variable_alias (p->decl, target_node->decl);
          alias_pairs->unordered_remove (i);
        }
        else
          error ("%q+D alias in between function and variable is not supported",
                 p->decl);
          warning (0, "%q+D aliased declaration",
-                  target_node->symbol.decl);
+                  target_node->decl);
          alias_pairs->unordered_remove (i);
        }
      }
@@@ -1206,34 -1209,34 +1209,34 @@@ mark_functions_to_output (void
  
    FOR_EACH_FUNCTION (node)
      {
-       tree decl = node->symbol.decl;
+       tree decl = node->decl;
  
-       gcc_assert (!node->process || node->symbol.same_comdat_group);
+       gcc_assert (!node->process || node->same_comdat_group);
        if (node->process)
        continue;
  
        /* We need to output all local functions that are used and not
         always inlined, as well as those that are reachable from
         outside the current compilation unit.  */
-       if (node->symbol.analyzed
+       if (node->analyzed
          && !node->thunk.thunk_p
-         && !node->symbol.alias
+         && !node->alias
          && !node->global.inlined_to
          && !TREE_ASM_WRITTEN (decl)
          && !DECL_EXTERNAL (decl))
        {
          node->process = 1;
-         if (node->symbol.same_comdat_group)
+         if (node->same_comdat_group)
            {
              struct cgraph_node *next;
-             for (next = cgraph (node->symbol.same_comdat_group);
+             for (next = cgraph (node->same_comdat_group);
                   next != node;
-                  next = cgraph (next->symbol.same_comdat_group))
-               if (!next->thunk.thunk_p && !next->symbol.alias)
+                  next = cgraph (next->same_comdat_group))
+               if (!next->thunk.thunk_p && !next->alias)
                  next->process = 1;
            }
        }
-       else if (node->symbol.same_comdat_group)
+       else if (node->same_comdat_group)
        {
  #ifdef ENABLE_CHECKING
          check_same_comdat_groups = true;
              /* FIXME: in ltrans unit when offline copy is outside partition but inline copies
                 are inside partition, we can end up not removing the body since we no longer
                 have analyzed node pointing to it.  */
-             && !node->symbol.in_other_partition
-             && !node->symbol.alias
+             && !node->in_other_partition
+             && !node->alias
              && !node->clones
              && !DECL_EXTERNAL (decl))
            {
  #endif
          gcc_assert (node->global.inlined_to
                      || !gimple_has_body_p (decl)
-                     || node->symbol.in_other_partition
+                     || node->in_other_partition
                      || node->clones
                      || DECL_ARTIFICIAL (decl)
                      || DECL_EXTERNAL (decl));
  #ifdef ENABLE_CHECKING
    if (check_same_comdat_groups)
      FOR_EACH_FUNCTION (node)
-       if (node->symbol.same_comdat_group && !node->process)
+       if (node->same_comdat_group && !node->process)
        {
-         tree decl = node->symbol.decl;
+         tree decl = node->decl;
          if (!node->global.inlined_to
              && gimple_has_body_p (decl)
              /* FIXME: in an ltrans unit when the offline copy is outside a
                 partition but inline copies are inside a partition, we can
                 end up not removing the body since we no longer have an
                 analyzed node pointing to it.  */
-             && !node->symbol.in_other_partition
+             && !node->in_other_partition
              && !node->clones
              && !DECL_EXTERNAL (decl))
            {
@@@ -1449,8 -1452,8 +1452,8 @@@ expand_thunk (struct cgraph_node *node
    HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset;
    HOST_WIDE_INT virtual_value = node->thunk.virtual_value;
    tree virtual_offset = NULL;
-   tree alias = node->callees->callee->symbol.decl;
-   tree thunk_fndecl = node->symbol.decl;
+   tree alias = node->callees->callee->decl;
+   tree thunk_fndecl = node->decl;
    tree a;
  
  
        set_cfun (NULL);
        TREE_ASM_WRITTEN (thunk_fndecl) = 1;
        node->thunk.thunk_p = false;
-       node->symbol.analyzed = false;
+       node->analyzed = false;
      }
    else
      {
@@@ -1688,20 -1691,20 +1691,20 @@@ assemble_thunks_and_aliases (struct cgr
        }
      else
        e = e->next_caller;
-   for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+   for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
                                             i, ref); i++)
      if (ref->use == IPA_REF_ALIAS)
        {
        struct cgraph_node *alias = ipa_ref_referring_node (ref);
-         bool saved_written = TREE_ASM_WRITTEN (node->symbol.decl);
+         bool saved_written = TREE_ASM_WRITTEN (node->decl);
  
        /* Force assemble_alias to really output the alias this time instead
           of buffering it in same alias pairs.  */
-       TREE_ASM_WRITTEN (node->symbol.decl) = 1;
-       do_assemble_alias (alias->symbol.decl,
-                          DECL_ASSEMBLER_NAME (node->symbol.decl));
+       TREE_ASM_WRITTEN (node->decl) = 1;
+       do_assemble_alias (alias->decl,
+                          DECL_ASSEMBLER_NAME (node->decl));
        assemble_thunks_and_aliases (alias);
-       TREE_ASM_WRITTEN (node->symbol.decl) = saved_written;
+       TREE_ASM_WRITTEN (node->decl) = saved_written;
        }
  }
  
  static void
  expand_function (struct cgraph_node *node)
  {
-   tree decl = node->symbol.decl;
+   tree decl = node->decl;
    location_t saved_loc;
  
    /* We ought to not compile any inline clones.  */
                                   larger_than_size))
        {
          unsigned int size_as_int
 -          = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
 +          = tree_to_hwi (TYPE_SIZE_UNIT (ret_type));
  
          if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
            warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes",
    /* Eliminate all call edges.  This is important so the GIMPLE_CALL no longer
       points to the dead function body.  */
    cgraph_node_remove_callees (node);
-   ipa_remove_all_references (&node->symbol.ref_list);
+   ipa_remove_all_references (&node->ref_list);
  }
  
  
@@@ -1903,9 -1906,9 +1906,9 @@@ output_in_order (void
  
    FOR_EACH_DEFINED_FUNCTION (pf)
      {
-       if (pf->process && !pf->thunk.thunk_p && !pf->symbol.alias)
+       if (pf->process && !pf->thunk.thunk_p && !pf->alias)
        {
-         i = pf->symbol.order;
+         i = pf->order;
          gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
          nodes[i].kind = ORDER_FUNCTION;
          nodes[i].u.f = pf;
      }
  
    FOR_EACH_DEFINED_VARIABLE (pv)
-     if (!DECL_EXTERNAL (pv->symbol.decl))
+     if (!DECL_EXTERNAL (pv->decl))
        {
-       i = pv->symbol.order;
+       i = pv->order;
        gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
        nodes[i].kind = ORDER_VAR;
        nodes[i].u.v = pv;
@@@ -2046,11 -2049,11 +2049,11 @@@ get_alias_symbol (tree decl
  static void
  output_weakrefs (void)
  {
-   symtab_node node;
+   symtab_node *node;
    FOR_EACH_SYMBOL (node)
-     if (node->symbol.alias
-         && !TREE_ASM_WRITTEN (node->symbol.decl)
-       && node->symbol.weakref)
+     if (node->alias
+         && !TREE_ASM_WRITTEN (node->decl)
+       && node->weakref)
        {
        tree target;
  
           alias.
           When alias target is defined, we need to fetch it from symtab reference,
           otherwise it is pointed to by alias_target.  */
-       if (node->symbol.alias_target)
-         target = (DECL_P (node->symbol.alias_target)
-                   ? DECL_ASSEMBLER_NAME (node->symbol.alias_target)
-                   : node->symbol.alias_target);
-       else if (node->symbol.analyzed)
-         target = DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl);
+       if (node->alias_target)
+         target = (DECL_P (node->alias_target)
+                   ? DECL_ASSEMBLER_NAME (node->alias_target)
+                   : node->alias_target);
+       else if (node->analyzed)
+         target = DECL_ASSEMBLER_NAME (symtab_alias_target (node)->decl);
        else
          {
            gcc_unreachable ();
-           target = get_alias_symbol (node->symbol.decl);
+           target = get_alias_symbol (node->decl);
          }
-         do_assemble_alias (node->symbol.decl, target);
+         do_assemble_alias (node->decl, target);
        }
  }
  
@@@ -2168,17 -2171,17 +2171,17 @@@ compile (void
       level by physically rewritting the IL.  At the moment we can only redirect
       calls, so we need infrastructure for renaming references as well.  */
  #ifndef ASM_OUTPUT_WEAKREF
-   symtab_node node;
+   symtab_node *node;
  
    FOR_EACH_SYMBOL (node)
-     if (node->symbol.alias
-       && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
+     if (node->alias
+       && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl)))
        {
        IDENTIFIER_TRANSPARENT_ALIAS
-          (DECL_ASSEMBLER_NAME (node->symbol.decl)) = 1;
-       TREE_CHAIN (DECL_ASSEMBLER_NAME (node->symbol.decl))
-          = (node->symbol.alias_target ? node->symbol.alias_target
-             : DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl));
+          (DECL_ASSEMBLER_NAME (node->decl)) = 1;
+       TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl))
+          = (node->alias_target ? node->alias_target
+             : DECL_ASSEMBLER_NAME (symtab_alias_target (node)->decl));
        }
  #endif
  
  
        FOR_EACH_DEFINED_FUNCTION (node)
        if (node->global.inlined_to
-           || gimple_has_body_p (node->symbol.decl))
+           || gimple_has_body_p (node->decl))
          {
            error_found = true;
            dump_cgraph_node (stderr, node);
diff --combined gcc/cilk-common.c
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);
+ }
index 33db421c964f286ed7b80dda3f7954fe19653d01,83d0c66706062c311cf24be248ba9541c973c48e..704e872fc61f3814ac9f682899fd021a06000ba4
@@@ -4263,6 -4263,24 +4263,24 @@@ aarch64_preferred_reload_class (rtx x, 
        && !aarch64_simd_imm_scalar_p (x, GET_MODE (x)))
      return NO_REGS;
  
+   /* Register eliminiation can result in a request for
+      SP+constant->FP_REGS.  We cannot support such operations which
+      use SP as source and an FP_REG as destination, so reject out
+      right now.  */
+   if (! reg_class_subset_p (regclass, GENERAL_REGS) && GET_CODE (x) == PLUS)
+     {
+       rtx lhs = XEXP (x, 0);
+       /* Look through a possible SUBREG introduced by ILP32.  */
+       if (GET_CODE (lhs) == SUBREG)
+       lhs = SUBREG_REG (lhs);
+       gcc_assert (REG_P (lhs));
+       gcc_assert (reg_class_subset_p (REGNO_REG_CLASS (REGNO (lhs)),
+                                     POINTER_REGS));
+       return NO_REGS;
+     }
    return regclass;
  }
  
@@@ -6020,17 -6038,19 +6038,17 @@@ aapcs_vfp_sub_candidate (const_tree typ
        if (count == -1
            || !index
            || !TYPE_MAX_VALUE (index)
 -          || !host_integerp (TYPE_MAX_VALUE (index), 1)
 +          || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index))
            || !TYPE_MIN_VALUE (index)
 -          || !host_integerp (TYPE_MIN_VALUE (index), 1)
 +          || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index))
            || count < 0)
          return -1;
  
 -      count *= (1 + tree_low_cst (TYPE_MAX_VALUE (index), 1)
 -                    - tree_low_cst (TYPE_MIN_VALUE (index), 1));
 +      count *= (1 + tree_to_uhwi (TYPE_MAX_VALUE (index))
 +                    - tree_to_uhwi (TYPE_MIN_VALUE (index)));
  
        /* There must be no padding.  */
 -      if (!host_integerp (TYPE_SIZE (type), 1)
 -          || (tree_low_cst (TYPE_SIZE (type), 1)
 -              != count * GET_MODE_BITSIZE (*modep)))
 +      if (wi::ne_p (TYPE_SIZE (type), count * GET_MODE_BITSIZE (*modep)))
          return -1;
  
        return count;
          }
  
        /* There must be no padding.  */
 -      if (!host_integerp (TYPE_SIZE (type), 1)
 -          || (tree_low_cst (TYPE_SIZE (type), 1)
 -              != count * GET_MODE_BITSIZE (*modep)))
 +      if (wi::ne_p (TYPE_SIZE (type), count * GET_MODE_BITSIZE (*modep)))
          return -1;
  
        return count;
          }
  
        /* There must be no padding.  */
 -      if (!host_integerp (TYPE_SIZE (type), 1)
 -          || (tree_low_cst (TYPE_SIZE (type), 1)
 -              != count * GET_MODE_BITSIZE (*modep)))
 +      if (wi::ne_p (TYPE_SIZE (type), count * GET_MODE_BITSIZE (*modep)))
          return -1;
  
        return count;
@@@ -6847,7 -6871,7 +6865,7 @@@ aarch64_simd_attr_length_move (rtx insn
  static HOST_WIDE_INT
  aarch64_simd_vector_alignment (const_tree type)
  {
 -  HOST_WIDE_INT align = tree_low_cst (TYPE_SIZE (type), 0);
 +  HOST_WIDE_INT align = tree_to_shwi (TYPE_SIZE (type));
    return MIN (align, 128);
  }
  
@@@ -7426,8 -7450,8 +7444,8 @@@ aarch64_float_const_representable_p (rt
    int point_pos = 2 * HOST_BITS_PER_WIDE_INT - 1;
    int exponent;
    unsigned HOST_WIDE_INT mantissa, mask;
 -  HOST_WIDE_INT m1, m2;
    REAL_VALUE_TYPE r, m;
 +  bool fail;
  
    if (!CONST_DOUBLE_P (x))
      return false;
       WARNING: If we ever have a representation using more than 2 * H_W_I - 1
       bits for the mantissa, this can fail (low bits will be lost).  */
    real_ldexp (&m, &r, point_pos - exponent);
 -  REAL_VALUE_TO_INT (&m1, &m2, m);
 +  wide_int w = real_to_integer (&m, &fail, HOST_BITS_PER_WIDE_INT * 2);
  
    /* If the low part of the mantissa has bits set we cannot represent
       the value.  */
 -  if (m1 != 0)
 +  if (w.elt (0) != 0)
      return false;
    /* We have rejected the lower HOST_WIDE_INT, so update our
       understanding of how many bits lie in the mantissa and
       look only at the high HOST_WIDE_INT.  */
 -  mantissa = m2;
 +  mantissa = w.elt (1);
    point_pos -= HOST_BITS_PER_WIDE_INT;
  
    /* We can only represent values with a mantissa of the form 1.xxxx.  */
diff --combined gcc/config/arm/arm.c
index 843fe97d5f88b9c020761796d13236d7548b739c,23dfc0e5cad88e920ce5d1d0078164e1776a3118..0b79023e706891cfcfe8c60a1bb39e6d3b7157be
@@@ -1076,18 -1076,18 +1076,18 @@@ const struct cpu_cost_table cortexa9_ex
      {
        COSTS_N_INSNS (3),      /* Simple.  */
        COSTS_N_INSNS (3),      /* Flag_setting.  */
-       COSTS_N_INSNS (4),      /* Extend.  */
+       COSTS_N_INSNS (2),      /* Extend.  */
        COSTS_N_INSNS (3),      /* Add.  */
-       COSTS_N_INSNS (4),      /* Extend_add.  */
+       COSTS_N_INSNS (2),      /* Extend_add.  */
        COSTS_N_INSNS (30)      /* Idiv.  No HW div on Cortex A9.  */
      },
      /* MULT DImode */
      {
        0,                      /* Simple (N/A).  */
        0,                      /* Flag_setting (N/A).  */
-       0,                      /* Extend (N/A).  */
+       COSTS_N_INSNS (4),      /* Extend.  */
        0,                      /* Add (N/A).  */
-       0,                      /* Extend_add (N/A).  */
+       COSTS_N_INSNS (4),      /* Extend_add.  */
        0                               /* Idiv (N/A).  */
      }
    },
  };
  
  
+ const struct cpu_cost_table cortexa7_extra_costs =
+ {
+   /* ALU */
+   {
+     0,                        /* Arith.  */
+     0,                        /* Logical.  */
+     COSTS_N_INSNS (1),        /* Shift.  */
+     COSTS_N_INSNS (1),        /* Shift_reg.  */
+     COSTS_N_INSNS (1),        /* Arith_shift.  */
+     COSTS_N_INSNS (1),        /* Arith_shift_reg.  */
+     COSTS_N_INSNS (1),        /* Log_shift.  */
+     COSTS_N_INSNS (1),        /* Log_shift_reg.  */
+     COSTS_N_INSNS (1),        /* Extend.  */
+     COSTS_N_INSNS (1),        /* Extend_arith.  */
+     COSTS_N_INSNS (1),        /* Bfi.  */
+     COSTS_N_INSNS (1),        /* Bfx.  */
+     COSTS_N_INSNS (1),        /* Clz.  */
+     0,                        /* non_exec.  */
+     true              /* non_exec_costs_exec.  */
+   },
+   {
+     /* MULT SImode */
+     {
+       0,                      /* Simple.  */
+       COSTS_N_INSNS (1),      /* Flag_setting.  */
+       COSTS_N_INSNS (1),      /* Extend.  */
+       COSTS_N_INSNS (1),      /* Add.  */
+       COSTS_N_INSNS (1),      /* Extend_add.  */
+       COSTS_N_INSNS (7)               /* Idiv.  */
+     },
+     /* MULT DImode */
+     {
+       0,                      /* Simple (N/A).  */
+       0,                      /* Flag_setting (N/A).  */
+       COSTS_N_INSNS (1),      /* Extend.  */
+       0,                      /* Add.  */
+       COSTS_N_INSNS (2),      /* Extend_add.  */
+       0                               /* Idiv (N/A).  */
+     }
+   },
+   /* LD/ST */
+   {
+     COSTS_N_INSNS (1),        /* Load.  */
+     COSTS_N_INSNS (1),        /* Load_sign_extend.  */
+     COSTS_N_INSNS (3),        /* Ldrd.  */
+     COSTS_N_INSNS (1),        /* Ldm_1st.  */
+     1,                        /* Ldm_regs_per_insn_1st.  */
+     2,                        /* Ldm_regs_per_insn_subsequent.  */
+     COSTS_N_INSNS (2),        /* Loadf.  */
+     COSTS_N_INSNS (2),        /* Loadd.  */
+     COSTS_N_INSNS (1),        /* Load_unaligned.  */
+     COSTS_N_INSNS (1),        /* Store.  */
+     COSTS_N_INSNS (3),        /* Strd.  */
+     COSTS_N_INSNS (1),        /* Stm_1st.  */
+     1,                        /* Stm_regs_per_insn_1st.  */
+     2,                        /* Stm_regs_per_insn_subsequent.  */
+     COSTS_N_INSNS (2),        /* Storef.  */
+     COSTS_N_INSNS (2),        /* Stored.  */
+     COSTS_N_INSNS (1) /* Store_unaligned.  */
+   },
+   {
+     /* FP SFmode */
+     {
+       COSTS_N_INSNS (15),     /* Div.  */
+       COSTS_N_INSNS (3),      /* Mult.  */
+       COSTS_N_INSNS (7),      /* Mult_addsub. */
+       COSTS_N_INSNS (7),      /* Fma.  */
+       COSTS_N_INSNS (3),      /* Addsub.  */
+       COSTS_N_INSNS (3),      /* Fpconst.  */
+       COSTS_N_INSNS (3),      /* Neg.  */
+       COSTS_N_INSNS (3),      /* Compare.  */
+       COSTS_N_INSNS (3),      /* Widen.  */
+       COSTS_N_INSNS (3),      /* Narrow.  */
+       COSTS_N_INSNS (3),      /* Toint.  */
+       COSTS_N_INSNS (3),      /* Fromint.  */
+       COSTS_N_INSNS (3)               /* Roundint.  */
+     },
+     /* FP DFmode */
+     {
+       COSTS_N_INSNS (30),     /* Div.  */
+       COSTS_N_INSNS (6),      /* Mult.  */
+       COSTS_N_INSNS (10),     /* Mult_addsub.  */
+       COSTS_N_INSNS (7),      /* Fma.  */
+       COSTS_N_INSNS (3),      /* Addsub.  */
+       COSTS_N_INSNS (3),      /* Fpconst.  */
+       COSTS_N_INSNS (3),      /* Neg.  */
+       COSTS_N_INSNS (3),      /* Compare.  */
+       COSTS_N_INSNS (3),      /* Widen.  */
+       COSTS_N_INSNS (3),      /* Narrow.  */
+       COSTS_N_INSNS (3),      /* Toint.  */
+       COSTS_N_INSNS (3),      /* Fromint.  */
+       COSTS_N_INSNS (3)               /* Roundint.  */
+     }
+   },
+   /* Vector */
+   {
+     COSTS_N_INSNS (1) /* Alu.  */
+   }
+ };
  const struct cpu_cost_table cortexa15_extra_costs =
  {
    /* ALU */
@@@ -1368,6 -1469,22 +1469,22 @@@ const struct tune_params arm_cortex_tun
    false                                         /* Prefer Neon for 64-bits bitops.  */
  };
  
+ const struct tune_params arm_cortex_a7_tune =
+ {
+   arm_9e_rtx_costs,
+   &cortexa7_extra_costs,
+   NULL,
+   1,                                          /* Constant limit.  */
+   5,                                          /* Max cond insns.  */
+   ARM_PREFETCH_NOT_BENEFICIAL,
+   false,                                      /* Prefer constant pool.  */
+   arm_default_branch_cost,
+   false,                                      /* Prefer LDRD/STRD.  */
+   {true, true},                                       /* Prefer non short circuit.  */
+   &arm_default_vec_cost,                      /* Vectorizer costs.  */
+   false                                               /* Prefer Neon for 64-bits bitops.  */
+ };
  const struct tune_params arm_cortex_a15_tune =
  {
    arm_9e_rtx_costs,
@@@ -4668,17 -4785,19 +4785,17 @@@ aapcs_vfp_sub_candidate (const_tree typ
        if (count == -1
            || !index
            || !TYPE_MAX_VALUE (index)
 -          || !host_integerp (TYPE_MAX_VALUE (index), 1)
 +          || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index))
            || !TYPE_MIN_VALUE (index)
 -          || !host_integerp (TYPE_MIN_VALUE (index), 1)
 +          || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index))
            || count < 0)
          return -1;
  
 -      count *= (1 + tree_low_cst (TYPE_MAX_VALUE (index), 1)
 -                    - tree_low_cst (TYPE_MIN_VALUE (index), 1));
 +      count *= (1 + tree_to_uhwi (TYPE_MAX_VALUE (index))
 +                    - tree_to_uhwi (TYPE_MIN_VALUE (index)));
  
        /* There must be no padding.  */
 -      if (!host_integerp (TYPE_SIZE (type), 1)
 -          || (tree_low_cst (TYPE_SIZE (type), 1)
 -              != count * GET_MODE_BITSIZE (*modep)))
 +      if (wi::ne_p (TYPE_SIZE (type), count * GET_MODE_BITSIZE (*modep)))
          return -1;
  
        return count;
          }
  
        /* There must be no padding.  */
 -      if (!host_integerp (TYPE_SIZE (type), 1)
 -          || (tree_low_cst (TYPE_SIZE (type), 1)
 -              != count * GET_MODE_BITSIZE (*modep)))
 +      if (wi::ne_p (TYPE_SIZE (type), count * GET_MODE_BITSIZE (*modep)))
          return -1;
  
        return count;
          }
  
        /* There must be no padding.  */
 -      if (!host_integerp (TYPE_SIZE (type), 1)
 -          || (tree_low_cst (TYPE_SIZE (type), 1)
 -              != count * GET_MODE_BITSIZE (*modep)))
 +      if (wi::ne_p (TYPE_SIZE (type), count * GET_MODE_BITSIZE (*modep)))
          return -1;
  
        return count;
@@@ -11272,8 -11395,8 +11389,8 @@@ vfp3_const_double_index (rtx x
    int sign, exponent;
    unsigned HOST_WIDE_INT mantissa, mant_hi;
    unsigned HOST_WIDE_INT mask;
 -  HOST_WIDE_INT m1, m2;
    int point_pos = 2 * HOST_BITS_PER_WIDE_INT - 1;
 +  bool fail;
  
    if (!TARGET_VFP3 || !CONST_DOUBLE_P (x))
      return -1;
       WARNING: If there's ever a VFP version which uses more than 2 * H_W_I - 1
       bits for the mantissa, this may fail (low bits would be lost).  */
    real_ldexp (&m, &r, point_pos - exponent);
 -  REAL_VALUE_TO_INT (&m1, &m2, m);
 -  mantissa = m1;
 -  mant_hi = m2;
 +  wide_int w = real_to_integer (&m, &fail, HOST_BITS_PER_WIDE_INT * 2);
 +  mantissa = w.elt (0);
 +  mant_hi = w.elt (1);
  
    /* If there are bits set in the low part of the mantissa, we can't
       represent this value.  */
@@@ -26424,6 -26547,7 +26541,7 @@@ arm_expand_epilogue_apcs_frame (bool re
    num_regs = bit_count (saved_regs_mask);
    if ((offsets->outgoing_args != (1 + num_regs)) || cfun->calls_alloca)
      {
+       emit_insn (gen_blockage ());
        /* Unwind the stack to just below the saved registers.  */
        emit_insn (gen_addsi3 (stack_pointer_rtx,
                               hard_frame_pointer_rtx,
@@@ -28743,7 -28867,7 +28861,7 @@@ arm_builtin_vectorized_function (tree f
  static HOST_WIDE_INT
  arm_vector_alignment (const_tree type)
  {
 -  HOST_WIDE_INT align = tree_low_cst (TYPE_SIZE (type), 0);
 +  HOST_WIDE_INT align = tree_to_shwi (TYPE_SIZE (type));
  
    if (TARGET_AAPCS_BASED)
      align = MIN (align, 64);
diff --combined gcc/config/avr/avr.c
index 6a2750994f5f4ea451df2388a6219e35ab724d63,e7e1c2f138bd1b57a23521027b62de18cf87a960..f0def13ae8f7c8489eae494c273cea6ab691f492
@@@ -11365,26 -11365,12 +11365,12 @@@ avr_expand_delay_cycles (rtx operands0
  }
  
  
- /* Return VAL * BASE + DIGIT.  BASE = 0 is shortcut for BASE = 2^{32}   */
- static wide_int
- avr_wide_int_push_digit (const wide_int &val, int base,
-                        unsigned HOST_WIDE_INT digit)
- {
-   val = 0 == base
-     ? val.llshift (32)
-     : val * base;
-   return val + digit;
- }
  /* Compute the image of x under f, i.e. perform   x --> f(x)    */
  
  static int
- avr_map (const wide_int &f, int x)
+ avr_map (unsigned int f, int x)
  {
-   return 0xf & f.lrshift (4*x).to_uhwi ();
+   return x < 8 ? (f >> (4 * x)) & 0xf : 0;
  }
  
  
    };
  
  static unsigned
- avr_map_metric (const wide_int &a, int mode)
+ avr_map_metric (unsigned int a, int mode)
  {
    unsigned i, metric = 0;
  
  bool
  avr_has_nibble_0xf (rtx ival)
  {
-   return 0 != avr_map_metric (wide_int::from_rtx (ival), MAP_MASK_PREIMAGE_F);
+   unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
+   return 0 != avr_map_metric (map, MAP_MASK_PREIMAGE_F);
  }
  
  
@@@ -11476,7 -11463,7 +11463,7 @@@ typedef struc
    int cost;
  
    /* The composition F o G^-1 (*, arg) for some function F */
-   wide_int map;
+   unsigned int map;
  
    /* For debug purpose only */
    const char *str;
  
  static const avr_map_op_t avr_map_op[] =
    {
-     { LROTATE_EXPR, 0, 0x76543210, 0, { 0, 0 }, "id" },
-     { LROTATE_EXPR, 1, 0x07654321, 2, { 0, 0 }, "<<<" },
-     { LROTATE_EXPR, 2, 0x10765432, 4, { 0, 0 }, "<<<" },
-     { LROTATE_EXPR, 3, 0x21076543, 4, { 0, 0 }, "<<<" },
-     { LROTATE_EXPR, 4, 0x32107654, 1, { 0, 0 }, "<<<" },
-     { LROTATE_EXPR, 5, 0x43210765, 3, { 0, 0 }, "<<<" },
-     { LROTATE_EXPR, 6, 0x54321076, 5, { 0, 0 }, "<<<" },
-     { LROTATE_EXPR, 7, 0x65432107, 3, { 0, 0 }, "<<<" },
-     { RSHIFT_EXPR, 1, 0x6543210c, 1, { 0, 0 }, ">>" },
-     { RSHIFT_EXPR, 1, 0x7543210c, 1, { 0, 0 }, ">>" },
-     { RSHIFT_EXPR, 2, 0x543210cc, 2, { 0, 0 }, ">>" },
-     { RSHIFT_EXPR, 2, 0x643210cc, 2, { 0, 0 }, ">>" },
-     { RSHIFT_EXPR, 2, 0x743210cc, 2, { 0, 0 }, ">>" },
-     { LSHIFT_EXPR, 1, 0xc7654321, 1, { 0, 0 }, "<<" },
-     { LSHIFT_EXPR, 2, 0xcc765432, 2, { 0, 0 }, "<<" }
+     { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
+     { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
+     { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
+     { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
+     { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
+     { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
+     { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
+     { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
+     { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
+     { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
+     { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
+     { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
+     { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
+     { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
+     { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
    };
  
  
     If result.cost < 0 then such a decomposition does not exist.  */
  
  static avr_map_op_t
- avr_map_decompose (const wide_int &f, const avr_map_op_t *g, bool val_const_p)
+ avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
  {
    int i;
    bool val_used_p = 0 != avr_map_metric (f, MAP_MASK_PREIMAGE_F);
    avr_map_op_t f_ginv = *g;
-   wide_int ginv = wide_int::from_uhwi (g->ginv);
+   unsigned int ginv = g->ginv;
  
    f_ginv.cost = -1;
  
              return f_ginv;
          }
  
-       f_ginv.map = avr_wide_int_push_digit (f_ginv.map, 16, x);
+       f_ginv.map = (f_ginv.map << 4) + x;
      }
  
    /* Step 2:  Compute the cost of the operations.
           are mapped to 0 and used operands are reloaded to xop[0].  */
  
        xop[0] = all_regs_rtx[24];
-       xop[1] = gen_int_mode (f_ginv.map.to_uhwi (), SImode);
+       xop[1] = gen_int_mode (f_ginv.map, SImode);
        xop[2] = all_regs_rtx[25];
        xop[3] = val_used_p ? xop[0] : const0_rtx;
  
     is different to its source position.  */
  
  static void
- avr_move_bits (rtx *xop, const wide_int &map, bool fixp_p, int *plen)
+ avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
  {
    int bit_dest, b;
  
  const char*
  avr_out_insert_bits (rtx *op, int *plen)
  {
-   wide_int map = wide_int::from_rtx (op[1]);
+   unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
    unsigned mask_fixed;
    bool fixp_p = true;
    rtx xop[4];
    if (plen)
      *plen = 0;
    else if (flag_print_asm_name)
-     fprintf (asm_out_file,
-              ASM_COMMENT_START "map = 0x%08" HOST_LONG_FORMAT "x\n",
-              map.to_uhwi () & GET_MODE_MASK (SImode));
+     fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
  
    /* If MAP has fixed points it might be better to initialize the result
       with the bits to be inserted instead of moving all bits by hand.  */
@@@ -12085,7 -12070,7 +12070,7 @@@ avr_expand_builtin (tree exp, rtx targe
        if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
          break;
  
 -      int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
 +      int rbit = (int) tree_to_hwi (CALL_EXPR_ARG (exp, 1));
  
        if (rbit >= (int) GET_MODE_FBIT (mode))
          {
@@@ -12228,6 -12213,7 +12213,7 @@@ avr_fold_builtin (tree fndecl, int n_ar
          tree tval = arg[2];
          tree tmap;
          tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
+         unsigned int map;
          bool changed = false;
          unsigned i;
          avr_map_op_t best_g;
              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))
              /* Inserting bits known at compile time is easy and can be
                 performed by AND and OR with appropriate masks.  */
  
 -            int bits = TREE_INT_CST_LOW (tbits);
 +            int bits = tree_to_hwi (tbits);
              int mask_ior = 0, mask_and = 0xff;
  
              for (i = 0; i < 8; i++)
          /* Try to decomposing map to reduce overall cost.  */
  
          if (avr_log.builtin)
-           avr_edump ("\n%?: %X\n%?: ROL cost: ", map);
+           avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
  
          best_g = avr_map_op[0];
          best_g.cost = 1000;
          /* Apply operation G to the 2nd argument.  */
  
          if (avr_log.builtin)
-           avr_edump ("%?: using OP(%s%d, %X) cost %d\n",
+           avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
                       best_g.str, best_g.arg, best_g.map, best_g.cost);
  
          /* Do right-shifts arithmetically: They copy the MSB instead of
  
          /* 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 */
diff --combined gcc/config/darwin.c
index 8d7c3cede899e5c8d9ebe07a8dab0d9db2ff0b55,fc7a9a8f99e9fc7e0cd2f3352c764cc64d2f95f1..661795dc9f09df1f09b732cebf64e775e8bbe159
@@@ -45,6 -45,7 +45,7 @@@ along with GCC; see the file COPYING3
  #include "df.h"
  #include "debug.h"
  #include "obstack.h"
+ #include "gimple.h"
  #include "lto-streamer.h"
  
  /* Darwin supports a feature called fix-and-continue, which is used
@@@ -1284,17 -1285,22 +1285,17 @@@ darwin_mergeable_constant_section (tre
      {
        tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
  
 -      if (TREE_CODE (size) == INTEGER_CST
 -        && TREE_INT_CST_LOW (size) == 4
 -        && TREE_INT_CST_HIGH (size) == 0)
 -        return darwin_sections[literal4_section];
 -      else if (TREE_CODE (size) == INTEGER_CST
 -             && TREE_INT_CST_LOW (size) == 8
 -             && TREE_INT_CST_HIGH (size) == 0)
 -        return darwin_sections[literal8_section];
 -      else if (HAVE_GAS_LITERAL16
 -             && TARGET_64BIT
 -               && TREE_CODE (size) == INTEGER_CST
 -               && TREE_INT_CST_LOW (size) == 16
 -               && TREE_INT_CST_HIGH (size) == 0)
 -        return darwin_sections[literal16_section];
 -      else
 -        return readonly_data_section;
 +      if (TREE_CODE (size) == INTEGER_CST)
 +      {
 +        if (wi::eq_p (size, 4))
 +          return darwin_sections[literal4_section];
 +        else if (wi::eq_p (size, 8))
 +          return darwin_sections[literal8_section];
 +        else if (HAVE_GAS_LITERAL16
 +                 && TARGET_64BIT
 +                 && wi::eq_p (size, 16))
 +          return darwin_sections[literal16_section];
 +      }
      }
  
    return readonly_data_section;
@@@ -1502,7 -1508,7 +1503,7 @@@ machopic_select_section (tree decl
  
    zsize = (DECL_P (decl) 
           && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL) 
 -         && tree_low_cst (DECL_SIZE_UNIT (decl), 1) == 0);
 +         && tree_to_uhwi (DECL_SIZE_UNIT (decl)) == 0);
  
    one = DECL_P (decl) 
        && TREE_CODE (decl) == VAR_DECL 
        static bool warned_objc_46 = false;
        /* We shall assert that zero-sized objects are an error in ObjC 
           meta-data.  */
 -      gcc_assert (tree_low_cst (DECL_SIZE_UNIT (decl), 1) != 0);
 +      gcc_assert (tree_to_uhwi (DECL_SIZE_UNIT (decl)) != 0);
        
        /* ??? This mechanism for determining the metadata section is
         broken when LTO is in use, since the frontend that generated
@@@ -1721,19 -1727,16 +1722,19 @@@ machopic_select_rtx_section (enum machi
  {
    if (GET_MODE_SIZE (mode) == 8
        && (GET_CODE (x) == CONST_INT
 +        || GET_CODE (x) == CONST_WIDE_INT
          || GET_CODE (x) == CONST_DOUBLE))
      return darwin_sections[literal8_section];
    else if (GET_MODE_SIZE (mode) == 4
           && (GET_CODE (x) == CONST_INT
 +             || GET_CODE (x) == CONST_WIDE_INT
               || GET_CODE (x) == CONST_DOUBLE))
      return darwin_sections[literal4_section];
    else if (HAVE_GAS_LITERAL16
           && TARGET_64BIT
           && GET_MODE_SIZE (mode) == 16
           && (GET_CODE (x) == CONST_INT
 +             || GET_CODE (x) == CONST_WIDE_INT
               || GET_CODE (x) == CONST_DOUBLE
               || GET_CODE (x) == CONST_VECTOR))
      return darwin_sections[literal16_section];
@@@ -2183,7 -2186,7 +2184,7 @@@ darwin_asm_declare_object_name (FILE *f
        machopic_define_symbol (DECL_RTL (decl));
      }
  
 -  size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
 +  size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
  
  #ifdef DEBUG_DARWIN_MEM_ALLOCATORS
  fprintf (file, "# dadon: %s %s (%llu, %u) local %d weak %d"
diff --combined gcc/config/i386/i386.c
index 4b69d4bf026b47a0c854302e32d4688992c44572,902e169960424d1f14ab478f9a71300c1225b887..bc93d7f849ac376ceb82fc83aefb9ee2d1a6068c
@@@ -61,7 -61,6 +61,7 @@@ along with GCC; see the file COPYING3
  #include "diagnostic.h"
  #include "dumpfile.h"
  #include "tree-pass.h"
 +#include "wide-int.h"
  #include "context.h"
  #include "pass_manager.h"
  
@@@ -1944,6 -1943,8 +1944,8 @@@ enum reg_class const regclass_map[FIRST
    /* Mask registers.  */
    MASK_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS,
    MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS,
+   /* MPX bound registers */
+   BND_REGS, BND_REGS, BND_REGS, BND_REGS,
  };
  
  /* The "default" register map used in 32bit mode.  */
@@@ -1960,6 -1961,7 +1962,7 @@@ int const dbx_register_map[FIRST_PSEUDO
    -1, -1, -1, -1, -1, -1, -1, -1,       /* AVX-512 registers 16-23*/
    -1, -1, -1, -1, -1, -1, -1, -1,       /* AVX-512 registers 24-31*/
    93, 94, 95, 96, 97, 98, 99, 100,      /* Mask registers */
+   101, 102, 103, 104,                 /* bound registers */
  };
  
  /* The "default" register map used in 64bit mode.  */
@@@ -1976,6 -1978,7 +1979,7 @@@ int const dbx64_register_map[FIRST_PSEU
    67, 68, 69, 70, 71, 72, 73, 74,       /* AVX-512 registers 16-23 */
    75, 76, 77, 78, 79, 80, 81, 82,       /* AVX-512 registers 24-31 */
    118, 119, 120, 121, 122, 123, 124, 125, /* Mask registers */
+   126, 127, 128, 129,                 /* bound registers */
  };
  
  /* Define the register numbers to be used in Dwarf debugging information.
@@@ -2044,6 -2047,7 +2048,7 @@@ int const svr4_dbx_register_map[FIRST_P
    -1, -1, -1, -1, -1, -1, -1, -1,       /* AVX-512 registers 16-23*/
    -1, -1, -1, -1, -1, -1, -1, -1,       /* AVX-512 registers 24-31*/
    93, 94, 95, 96, 97, 98, 99, 100,      /* Mask registers */
+   -1, -1, -1, -1,                       /* bound registers */
  };
  
  /* Define parameter passing and return registers.  */
@@@ -2470,6 -2474,7 +2475,7 @@@ ix86_target_string (HOST_WIDE_INT isa, 
      { "-mrtm",                OPTION_MASK_ISA_RTM },
      { "-mxsave",      OPTION_MASK_ISA_XSAVE },
      { "-mxsaveopt",   OPTION_MASK_ISA_XSAVEOPT },
+     { "-mmpx",          OPTION_MASK_ISA_MPX },
    };
  
    /* Flag options.  */
@@@ -2964,6 -2969,7 +2970,7 @@@ ix86_option_override_internal (bool mai
  #define PTA_AVX512ER          (HOST_WIDE_INT_1 << 41)
  #define PTA_AVX512PF          (HOST_WIDE_INT_1 << 42)
  #define PTA_AVX512CD          (HOST_WIDE_INT_1 << 43)
+ #define PTA_MPX                       (HOST_WIDE_INT_1 << 44)
  
  /* if this reaches 64, need to widen struct pta flags below */
  
       codegen.  We may switch to 387 with -ffast-math for size optimized
       functions. */
    else if (fast_math_flags_set_p (&global_options)
-          && TARGET_SSE2)
+          && TARGET_SSE2_P (opts->x_ix86_isa_flags))
      ix86_fpmath = FPMATH_SSE;
    else
      opts->x_ix86_fpmath = TARGET_FPMATH_DEFAULT_P (opts->x_ix86_isa_flags);
@@@ -4149,6 -4155,11 +4156,11 @@@ ix86_conditional_register_usage (void
        for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++)
        fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
      }
+   /* If MPX is disabled, squash the registers.  */
+   if (! TARGET_MPX)
+     for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++)
+       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
  }
  
  \f
@@@ -4554,7 -4565,8 +4566,8 @@@ ix86_valid_target_attribute_tree (tree 
        /* If fpmath= is not set, and we now have sse2 on 32-bit, use it.  */
        if (enum_opts_set.x_ix86_fpmath)
        opts_set->x_ix86_fpmath = (enum fpmath_unit) 1;
-       else if (!TARGET_64BIT && TARGET_SSE)
+       else if (!TARGET_64BIT_P (opts->x_ix86_isa_flags)
+              && TARGET_SSE_P (opts->x_ix86_isa_flags))
        {
          opts->x_ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387);
          opts_set->x_ix86_fpmath = (enum fpmath_unit) 1;
@@@ -5361,7 -5373,7 +5374,7 @@@ ix86_function_regparm (const_tree type
        attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
        if (attr)
        {
 -        regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
 +        regparm = tree_to_hwi (TREE_VALUE (TREE_VALUE (attr)));
          return regparm;
        }
      }
@@@ -5488,7 -5500,7 +5501,7 @@@ ix86_keep_aggregate_return_pointer (tre
        attr = lookup_attribute ("callee_pop_aggregate_return",
                               TYPE_ATTRIBUTES (fntype));
        if (attr)
 -      return (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))) == 0);
 +      return (tree_to_hwi (TREE_VALUE (TREE_VALUE (attr))) == 0);
  
        /* For 32-bit MS-ABI the default is to keep aggregate
           return pointer.  */
@@@ -6157,7 -6169,7 +6170,7 @@@ classify_argument (enum machine_mode mo
                      for (i = (int_bit_position (field)
                                + (bit_offset % 64)) / 8 / 8;
                           i < ((int_bit_position (field) + (bit_offset % 64))
 -                              + tree_low_cst (DECL_SIZE (field), 0)
 +                              + tree_to_shwi (DECL_SIZE (field))
                                + 63) / 8 / 8; i++)
                        classes[i] =
                          merge_classes (X86_64_INTEGER_CLASS,
@@@ -8870,7 -8882,7 +8883,7 @@@ ix86_code_end (void
        xops[0] = gen_rtx_REG (Pmode, regno);
        xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
        output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops);
-       fputs ("\tret\n", asm_out_file);
+       output_asm_insn ("%!ret", NULL);
        final_end_function ();
        init_insn_lengths ();
        free_after_compilation (cfun);
@@@ -8928,7 -8940,7 +8941,7 @@@ output_set_got (rtx dest, rtx label
  
        xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
        xops[2] = gen_rtx_MEM (QImode, xops[2]);
-       output_asm_insn ("call\t%X2", xops);
+       output_asm_insn ("%!call\t%X2", xops);
  
  #if TARGET_MACHO
        /* Output the Mach-O "canonical" pic base label name ("Lxx$pb") here.
@@@ -14104,8 -14116,6 +14117,6 @@@ put_condition_code (enum rtx_code code
         Those same assemblers have the same but opposite lossage on cmov.  */
        if (mode == CCmode)
        suffix = fp ? "nbe" : "a";
-       else if (mode == CCCmode)
-       suffix = "b";
        else
        gcc_unreachable ();
        break;
        }
        break;
      case LTU:
-       gcc_assert (mode == CCmode || mode == CCCmode);
-       suffix = "b";
+       if (mode == CCmode)
+       suffix = "b";
+       else if (mode == CCCmode)
+       suffix = "c";
+       else
+       gcc_unreachable ();
        break;
      case GE:
        switch (mode)
        }
        break;
      case GEU:
-       /* ??? As above.  */
-       gcc_assert (mode == CCmode || mode == CCCmode);
-       suffix = fp ? "nb" : "ae";
+       if (mode == CCmode)
+       suffix = fp ? "nb" : "ae";
+       else if (mode == CCCmode)
+       suffix = "nc";
+       else
+       gcc_unreachable ();
        break;
      case LE:
        gcc_assert (mode == CCmode || mode == CCGCmode || mode == CCNOmode);
        suffix = "le";
        break;
      case LEU:
-       /* ??? As above.  */
        if (mode == CCmode)
        suffix = "be";
-       else if (mode == CCCmode)
-       suffix = fp ? "nb" : "ae";
        else
        gcc_unreachable ();
        break;
@@@ -14279,7 -14293,7 +14294,7 @@@ print_reg (rtx x, int code, FILE *file
      case 8:
      case 4:
      case 12:
-       if (! ANY_FP_REG_P (x))
+       if (! ANY_FP_REG_P (x) &&  ! ANY_BND_REG_P (x))
        putc (code == 8 && TARGET_64BIT ? 'r' : 'e', file);
        /* FALLTHRU */
      case 16:
@@@ -14402,6 -14416,7 +14417,7 @@@ get_some_local_dynamic_name (void
     ~ -- print "i" if TARGET_AVX2, "f" otherwise.
     @ -- print a segment register of thread base pointer load
     ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
+    ! -- print MPX prefix for jxx/call/ret instructions if required.
   */
  
  void
@@@ -14896,6 -14911,11 +14912,11 @@@ ix86_print_operand (FILE *file, rtx x, 
            fputs ("addr32 ", file);
          return;
  
+       case '!':
+         if (ix86_bnd_prefixed_insn_p (NULL_RTX))
+           fputs ("bnd ", file);
+         return;
        default:
            output_operand_lossage ("invalid operand code '%c'", code);
        }
@@@ -15038,7 -15058,7 +15059,7 @@@ static boo
  ix86_print_operand_punct_valid_p (unsigned char code)
  {
    return (code == '@' || code == '*' || code == '+' || code == '&'
-         || code == ';' || code == '~' || code == '^');
+         || code == ';' || code == '~' || code == '^' || code == '!');
  }
  \f
  /* Print a memory operand whose address is ADDR.  */
@@@ -15068,6 -15088,25 +15089,25 @@@ ix86_print_operand_address (FILE *file
        ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
        code = 'q';
      }
+   else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDMK_ADDR)
+     {
+       ok = ix86_decompose_address (XVECEXP (addr, 0, 1), &parts);
+       gcc_assert (parts.base == NULL_RTX || parts.index == NULL_RTX);
+       if (parts.base != NULL_RTX)
+       {
+         parts.index = parts.base;
+         parts.scale = 1;
+       }
+       parts.base = XVECEXP (addr, 0, 0);
+       addr = XVECEXP (addr, 0, 0);
+     }
+   else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDLDX_ADDR)
+     {
+       ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
+       gcc_assert (parts.index == NULL_RTX);
+       parts.index = XVECEXP (addr, 0, 1);
+       addr = XVECEXP (addr, 0, 0);
+     }
    else
      ok = ix86_decompose_address (addr, &parts);
  
@@@ -16521,6 -16560,12 +16561,12 @@@ ix86_avx256_split_vector_move_misalign 
          r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
          emit_move_insn (op0, r);
        }
+       /* Normal *mov<mode>_internal pattern will handle
+        unaligned loads just fine if misaligned_operand
+        is true, and without the UNSPEC it can be combined
+        with arithmetic instructions.  */
+       else if (misaligned_operand (op1, GET_MODE (op1)))
+       emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
        else
        emit_insn (load_unaligned (op0, op1));
      }
  void
  ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
  {
-   rtx op0, op1, m;
+   rtx op0, op1, orig_op0 = NULL_RTX, m;
    rtx (*load_unaligned) (rtx, rtx);
    rtx (*store_unaligned) (rtx, rtx);
  
        {
        case MODE_VECTOR_INT:
        case MODE_INT:
-         op0 = gen_lowpart (V16SImode, op0);
+         if (GET_MODE (op0) != V16SImode)
+           {
+             if (!MEM_P (op0))
+               {
+                 orig_op0 = op0;
+                 op0 = gen_reg_rtx (V16SImode);
+               }
+             else
+               op0 = gen_lowpart (V16SImode, op0);
+           }
          op1 = gen_lowpart (V16SImode, op1);
          /* FALLTHRU */
  
            emit_insn (store_unaligned (op0, op1));
          else
            gcc_unreachable ();
+         if (orig_op0)
+           emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
          break;
  
        default:
        {
        case MODE_VECTOR_INT:
        case MODE_INT:
-         op0 = gen_lowpart (V32QImode, op0);
+         if (GET_MODE (op0) != V32QImode)
+           {
+             if (!MEM_P (op0))
+               {
+                 orig_op0 = op0;
+                 op0 = gen_reg_rtx (V32QImode);
+               }
+             else
+               op0 = gen_lowpart (V32QImode, op0);
+           }
          op1 = gen_lowpart (V32QImode, op1);
          /* FALLTHRU */
  
        case MODE_VECTOR_FLOAT:
          ix86_avx256_split_vector_move_misalign (op0, op1);
+         if (orig_op0)
+           emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
          break;
  
        default:
  
    if (MEM_P (op1))
      {
+       /* Normal *mov<mode>_internal pattern will handle
+        unaligned loads just fine if misaligned_operand
+        is true, and without the UNSPEC it can be combined
+        with arithmetic instructions.  */
+       if (TARGET_AVX
+         && (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+             || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+         && misaligned_operand (op1, GET_MODE (op1)))
+       emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
        /* ??? If we have typed data, then it would appear that using
         movdqu is the only way to get unaligned data loaded with
         integer type.  */
-       if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
+       else if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
        {
-         op0 = gen_lowpart (V16QImode, op0);
+         if (GET_MODE (op0) != V16QImode)
+           {
+             orig_op0 = op0;
+             op0 = gen_reg_rtx (V16QImode);
+           }
          op1 = gen_lowpart (V16QImode, op1);
          /* We will eventually emit movups based on insn attributes.  */
          emit_insn (gen_sse2_loaddquv16qi (op0, op1));
+         if (orig_op0)
+           emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
        }
        else if (TARGET_SSE2 && mode == V2DFmode)
          {
        }
        else
          {
+         rtx t;
          if (TARGET_AVX
              || TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
              || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL
              || optimize_insn_for_size_p ())
            {
-             op0 = gen_lowpart (V4SFmode, op0);
+             if (GET_MODE (op0) != V4SFmode)
+               {
+                 orig_op0 = op0;
+                 op0 = gen_reg_rtx (V4SFmode);
+               }
              op1 = gen_lowpart (V4SFmode, op1);
              emit_insn (gen_sse_loadups (op0, op1));
+             if (orig_op0)
+               emit_move_insn (orig_op0,
+                               gen_lowpart (GET_MODE (orig_op0), op0));
              return;
              }
  
+         if (mode != V4SFmode)
+           t = gen_reg_rtx (V4SFmode);
+         else
+           t = op0;
+           
          if (TARGET_SSE_PARTIAL_REG_DEPENDENCY)
-           emit_move_insn (op0, CONST0_RTX (mode));
+           emit_move_insn (t, CONST0_RTX (V4SFmode));
          else
-           emit_clobber (op0);
-         if (mode != V4SFmode)
-           op0 = gen_lowpart (V4SFmode, op0);
+           emit_clobber (t);
  
          m = adjust_address (op1, V2SFmode, 0);
-         emit_insn (gen_sse_loadlps (op0, op0, m));
+         emit_insn (gen_sse_loadlps (t, t, m));
          m = adjust_address (op1, V2SFmode, 8);
-         emit_insn (gen_sse_loadhps (op0, op0, m));
+         emit_insn (gen_sse_loadhps (t, t, m));
+         if (mode != V4SFmode)
+           emit_move_insn (op0, gen_lowpart (mode, t));
        }
      }
    else if (MEM_P (op0))
@@@ -18863,12 -18958,7 +18959,7 @@@ ix86_cc_mode (enum rtx_code code, rtx o
        return CCmode;
      case GTU:                 /* CF=0 & ZF=0 */
      case LEU:                 /* CF=1 | ZF=1 */
-       /* Detect overflow checks.  They need just the carry flag.  */
-       if (GET_CODE (op0) == MINUS
-         && rtx_equal_p (op1, XEXP (op0, 0)))
-       return CCCmode;
-       else
-       return CCmode;
+       return CCmode;
        /* Codes possibly doable only with sign flag when
           comparing against zero.  */
      case GE:                  /* SF=OF   or   SF=0 */
@@@ -20389,6 -20479,7 +20480,7 @@@ ix86_expand_sse_movcc (rtx dest, rtx cm
    else
      {
        rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
+       rtx d = dest;
  
        if (!nonimmediate_operand (op_true, mode))
        op_true = force_reg (mode, op_true);
          if (TARGET_SSE4_1)
            {
              gen = gen_sse4_1_pblendvb;
-             dest = gen_lowpart (V16QImode, dest);
+             if (mode != V16QImode)
+               d = gen_reg_rtx (V16QImode);
              op_false = gen_lowpart (V16QImode, op_false);
              op_true = gen_lowpart (V16QImode, op_true);
              cmp = gen_lowpart (V16QImode, cmp);
          if (TARGET_AVX2)
            {
              gen = gen_avx2_pblendvb;
-             dest = gen_lowpart (V32QImode, dest);
+             if (mode != V32QImode)
+               d = gen_reg_rtx (V32QImode);
              op_false = gen_lowpart (V32QImode, op_false);
              op_true = gen_lowpart (V32QImode, op_true);
              cmp = gen_lowpart (V32QImode, cmp);
        }
  
        if (gen != NULL)
-       emit_insn (gen (dest, op_false, op_true, cmp));
+       {
+         emit_insn (gen (d, op_false, op_true, cmp));
+         if (d != dest)
+           emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
+       }
        else
        {
          op_true = force_reg (mode, op_true);
@@@ -20765,8 -20862,7 +20863,7 @@@ ix86_expand_int_vcond (rtx operands[]
    else
      {
        gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
-       x = ix86_expand_sse_cmp (gen_lowpart (mode, operands[0]),
-                              code, cop0, cop1,
+       x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1,
                               operands[1+negate], operands[2-negate]);
        x = gen_lowpart (data_mode, x);
      }
@@@ -20785,7 -20881,7 +20882,7 @@@ ix86_expand_vec_perm (rtx operands[]
    rtx op0 = operands[1];
    rtx op1 = operands[2];
    rtx mask = operands[3];
-   rtx t1, t2, t3, t4, vt, vt2, vec[32];
+   rtx t1, t2, t3, t4, t5, t6, t7, t8, vt, vt2, vec[32];
    enum machine_mode mode = GET_MODE (op0);
    enum machine_mode maskmode = GET_MODE (mask);
    int w, e, i;
  
          /* Continue as if V8SImode (resp. V32QImode) was used initially.  */
          operands[3] = mask = t1;
-         target = gen_lowpart (mode, target);
+         target = gen_reg_rtx (mode);
          op0 = gen_lowpart (mode, op0);
          op1 = gen_lowpart (mode, op1);
        }
             the high bits of the shuffle elements.  No need for us to
             perform an AND ourselves.  */
          if (one_operand_shuffle)
-           emit_insn (gen_avx2_permvarv8si (target, op0, mask));
+           {
+             emit_insn (gen_avx2_permvarv8si (target, op0, mask));
+             if (target != operands[0])
+               emit_move_insn (operands[0],
+                               gen_lowpart (GET_MODE (operands[0]), target));
+           }
          else
            {
              t1 = gen_reg_rtx (V8SImode);
             stands for other 12 bytes.  */
          /* The bit whether element is from the same lane or the other
             lane is bit 4, so shift it up by 3 to the MSB position.  */
-         emit_insn (gen_ashlv4di3 (gen_lowpart (V4DImode, t1),
-                                   gen_lowpart (V4DImode, mask),
+         t5 = gen_reg_rtx (V4DImode);
+         emit_insn (gen_ashlv4di3 (t5, gen_lowpart (V4DImode, mask),
                                    GEN_INT (3)));
          /* Clear MSB bits from the mask just in case it had them set.  */
          emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask));
          /* After this t1 will have MSB set for elements from other lane.  */
-         emit_insn (gen_xorv32qi3 (t1, t1, vt2));
+         emit_insn (gen_xorv32qi3 (t1, gen_lowpart (V32QImode, t5), vt2));
          /* Clear bits other than MSB.  */
          emit_insn (gen_andv32qi3 (t1, t1, vt));
          /* Or in the lower bits from mask into t3.  */
             lane.  */
          emit_insn (gen_xorv32qi3 (t1, t1, vt));
          /* Swap 128-bit lanes in t3.  */
-         emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
-                                         gen_lowpart (V4DImode, t3),
+         t6 = gen_reg_rtx (V4DImode);
+         emit_insn (gen_avx2_permv4di_1 (t6, gen_lowpart (V4DImode, t3),
                                          const2_rtx, GEN_INT (3),
                                          const0_rtx, const1_rtx));
          /* And or in the lower bits from mask into t1.  */
              /* Each of these shuffles will put 0s in places where
                 element from the other 128-bit lane is needed, otherwise
                 will shuffle in the requested value.  */
-             emit_insn (gen_avx2_pshufbv32qi3 (t3, op0, t3));
+             emit_insn (gen_avx2_pshufbv32qi3 (t3, op0,
+                                               gen_lowpart (V32QImode, t6)));
              emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1));
              /* For t3 the 128-bit lanes are swapped again.  */
-             emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
-                                             gen_lowpart (V4DImode, t3),
+             t7 = gen_reg_rtx (V4DImode);
+             emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t3),
                                              const2_rtx, GEN_INT (3),
                                              const0_rtx, const1_rtx));
              /* And oring both together leads to the result.  */
-             emit_insn (gen_iorv32qi3 (target, t1, t3));
+             emit_insn (gen_iorv32qi3 (target, t1,
+                                       gen_lowpart (V32QImode, t7)));
+             if (target != operands[0])
+               emit_move_insn (operands[0],
+                               gen_lowpart (GET_MODE (operands[0]), target));
              return;
            }
  
          /* Similarly to the above one_operand_shuffle code,
             just for repeated twice for each operand.  merge_two:
             code will merge the two results together.  */
-         emit_insn (gen_avx2_pshufbv32qi3 (t4, op0, t3));
-         emit_insn (gen_avx2_pshufbv32qi3 (t3, op1, t3));
+         emit_insn (gen_avx2_pshufbv32qi3 (t4, op0,
+                                           gen_lowpart (V32QImode, t6)));
+         emit_insn (gen_avx2_pshufbv32qi3 (t3, op1,
+                                           gen_lowpart (V32QImode, t6)));
          emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1));
          emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1));
-         emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t4),
-                                         gen_lowpart (V4DImode, t4),
+         t7 = gen_reg_rtx (V4DImode);
+         emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t4),
                                          const2_rtx, GEN_INT (3),
                                          const0_rtx, const1_rtx));
-         emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
-                                         gen_lowpart (V4DImode, t3),
+         t8 = gen_reg_rtx (V4DImode);
+         emit_insn (gen_avx2_permv4di_1 (t8, gen_lowpart (V4DImode, t3),
                                          const2_rtx, GEN_INT (3),
                                          const0_rtx, const1_rtx));
-         emit_insn (gen_iorv32qi3 (t4, t2, t4));
-         emit_insn (gen_iorv32qi3 (t3, t1, t3));
+         emit_insn (gen_iorv32qi3 (t4, t2, gen_lowpart (V32QImode, t7)));
+         emit_insn (gen_iorv32qi3 (t3, t1, gen_lowpart (V32QImode, t8)));
          t1 = t4;
          t2 = t3;
          goto merge_two;
    /* The actual shuffle operations all operate on V16QImode.  */
    op0 = gen_lowpart (V16QImode, op0);
    op1 = gen_lowpart (V16QImode, op1);
-   target = gen_lowpart (V16QImode, target);
  
    if (TARGET_XOP)
      {
+       if (GET_MODE (target) != V16QImode)
+       target = gen_reg_rtx (V16QImode);
        emit_insn (gen_xop_pperm (target, op0, op1, mask));
+       if (target != operands[0])
+       emit_move_insn (operands[0],
+                       gen_lowpart (GET_MODE (operands[0]), target));
      }
    else if (one_operand_shuffle)
      {
+       if (GET_MODE (target) != V16QImode)
+       target = gen_reg_rtx (V16QImode);
        emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask));
+       if (target != operands[0])
+       emit_move_insn (operands[0],
+                       gen_lowpart (GET_MODE (operands[0]), target));
      }
    else
      {
        mask = expand_simple_binop (maskmode, AND, mask, vt,
                                  NULL_RTX, 0, OPTAB_DIRECT);
  
-       xops[0] = gen_lowpart (mode, operands[0]);
+       if (GET_MODE (target) != mode)
+       target = gen_reg_rtx (mode);
+       xops[0] = target;
        xops[1] = gen_lowpart (mode, t2);
        xops[2] = gen_lowpart (mode, t1);
        xops[3] = gen_rtx_EQ (maskmode, mask, vt);
        xops[5] = vt;
        ok = ix86_expand_int_vcond (xops);
        gcc_assert (ok);
+       if (target != operands[0])
+       emit_move_insn (operands[0],
+                       gen_lowpart (GET_MODE (operands[0]), target));
      }
  }
  
@@@ -21196,10 -21318,10 +21319,10 @@@ ix86_expand_sse_unpack (rtx dest, rtx s
        else if (high_p)
        {
          /* Shift higher 8 bytes to lower 8 bytes.  */
-         tmp = gen_reg_rtx (imode);
-         emit_insn (gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, tmp),
-                                        gen_lowpart (V1TImode, src),
+         tmp = gen_reg_rtx (V1TImode);
+         emit_insn (gen_sse2_lshrv1ti3 (tmp, gen_lowpart (V1TImode, src),
                                         GEN_INT (64)));
+         tmp = gen_lowpart (imode, tmp);
        }
        else
        tmp = src;
        tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
                                   src, pc_rtx, pc_rtx);
  
-       emit_insn (unpack (gen_lowpart (imode, dest), src, tmp));
+       rtx tmp2 = gen_reg_rtx (imode);
+       emit_insn (unpack (tmp2, src, tmp));
+       emit_move_insn (dest, gen_lowpart (GET_MODE (dest), tmp2));
      }
  }
  
@@@ -22132,10 -22256,10 +22257,10 @@@ ix86_copy_addr_to_reg (rtx addr
      }
  }
  
- /* When SRCPTR is non-NULL, output simple loop to move memory
-    pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times,
-    overall size is COUNT specified in bytes.  When SRCPTR is NULL, output the
-    equivalent loop to set memory by VALUE (supposed to be in MODE).
+ /* When ISSETMEM is FALSE, output simple loop to move memory pointer to SRCPTR
+    to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT
+    specified in bytes.  When ISSETMEM is TRUE, output the equivalent loop to set
+    memory by VALUE (supposed to be in MODE).
  
     The size is rounded down to whole number of chunk size moved at once.
     SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info.  */
@@@ -22145,7 -22269,7 +22270,7 @@@ static voi
  expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
                               rtx destptr, rtx srcptr, rtx value,
                               rtx count, enum machine_mode mode, int unroll,
-                              int expected_size)
+                              int expected_size, bool issetmem)
  {
    rtx out_label, top_label, iter, tmp;
    enum machine_mode iter_mode = counter_mode (count);
    destmem = offset_address (destmem, tmp, piece_size_n);
    destmem = adjust_address (destmem, mode, 0);
  
-   if (srcmem)
+   if (!issetmem)
      {
        srcmem = offset_address (srcmem, copy_rtx (tmp), piece_size_n);
        srcmem = adjust_address (srcmem, mode, 0);
                             true, OPTAB_LIB_WIDEN);
    if (tmp != destptr)
      emit_move_insn (destptr, tmp);
-   if (srcptr)
+   if (!issetmem)
      {
        tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
                                 true, OPTAB_LIB_WIDEN);
    emit_label (out_label);
  }
  
- /* Output "rep; mov" instruction.
-    Arguments have same meaning as for previous function */
+ /* Output "rep; mov" or "rep; stos" instruction depending on ISSETMEM argument.
+    When ISSETMEM is true, arguments SRCMEM and SRCPTR are ignored.
+    When ISSETMEM is false, arguments VALUE and ORIG_VALUE are ignored.
+    For setmem case, VALUE is a promoted to a wider size ORIG_VALUE.
+    ORIG_VALUE is the original value passed to memset to fill the memory with.
+    Other arguments have same meaning as for previous function.  */
  static void
- expand_movmem_via_rep_mov (rtx destmem, rtx srcmem,
-                          rtx destptr, rtx srcptr,
+ expand_set_or_movmem_via_rep (rtx destmem, rtx srcmem,
+                          rtx destptr, rtx srcptr, rtx value, rtx orig_value,
                           rtx count,
-                          enum machine_mode mode)
+                          enum machine_mode mode, bool issetmem)
  {
    rtx destexp;
    rtx srcexp;
    rtx countreg;
    HOST_WIDE_INT rounded_count;
  
-   /* If the size is known, it is shorter to use rep movs.  */
-   if (mode == QImode && CONST_INT_P (count)
-       && !(INTVAL (count) & 3))
+   /* If possible, it is shorter to use rep movs.
+      TODO: Maybe it is better to move this logic to decide_alg.  */
+   if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3)
+       && (!issetmem || orig_value == const0_rtx))
      mode = SImode;
  
    if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
      destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
-   if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
-     srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
-   countreg = ix86_zero_extend_to_Pmode (scale_counter (count, GET_MODE_SIZE (mode)));
+   countreg = ix86_zero_extend_to_Pmode (scale_counter (count,
+                                                      GET_MODE_SIZE (mode)));
    if (mode != QImode)
      {
        destexp = gen_rtx_ASHIFT (Pmode, countreg,
                                GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
        destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
-       srcexp = gen_rtx_ASHIFT (Pmode, countreg,
-                              GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
-       srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
      }
    else
-     {
-       destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
-       srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
-     }
-   if (CONST_INT_P (count))
+     destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
+   if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count))
      {
        rounded_count = (INTVAL (count)
                       & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
        destmem = shallow_copy_rtx (destmem);
-       srcmem = shallow_copy_rtx (srcmem);
        set_mem_size (destmem, rounded_count);
-       set_mem_size (srcmem, rounded_count);
      }
-   else
-     {
-       if (MEM_SIZE_KNOWN_P (destmem))
-       clear_mem_size (destmem);
-       if (MEM_SIZE_KNOWN_P (srcmem))
-       clear_mem_size (srcmem);
-     }
-   emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
-                         destexp, srcexp));
- }
- /* Output "rep; stos" instruction.
-    Arguments have same meaning as for previous function */
- static void
- expand_setmem_via_rep_stos (rtx destmem, rtx destptr, rtx value,
-                           rtx count, enum machine_mode mode,
-                           rtx orig_value)
- {
-   rtx destexp;
-   rtx countreg;
-   HOST_WIDE_INT rounded_count;
+   else if (MEM_SIZE_KNOWN_P (destmem))
+     clear_mem_size (destmem);
  
-   if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
-     destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
-   value = force_reg (mode, gen_lowpart (mode, value));
-   countreg = ix86_zero_extend_to_Pmode (scale_counter (count, GET_MODE_SIZE (mode)));
-   if (mode != QImode)
+   if (issetmem)
      {
-       destexp = gen_rtx_ASHIFT (Pmode, countreg,
-                               GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
-       destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
+       value = force_reg (mode, gen_lowpart (mode, value));
+       emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
      }
    else
-     destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
-   if (orig_value == const0_rtx && CONST_INT_P (count))
      {
-       rounded_count = (INTVAL (count)
-                      & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
-       destmem = shallow_copy_rtx (destmem);
-       set_mem_size (destmem, rounded_count);
+       if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
+       srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
+       if (mode != QImode)
+       {
+         srcexp = gen_rtx_ASHIFT (Pmode, countreg,
+                                  GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
+         srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
+       }
+       else
+       srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
+       if (CONST_INT_P (count))
+       {
+         rounded_count = (INTVAL (count)
+                          & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
+         srcmem = shallow_copy_rtx (srcmem);
+         set_mem_size (srcmem, rounded_count);
+       }
+       else
+       {
+         if (MEM_SIZE_KNOWN_P (srcmem))
+           clear_mem_size (srcmem);
+       }
+       emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
+                             destexp, srcexp));
      }
-   else if (MEM_SIZE_KNOWN_P (destmem))
-     clear_mem_size (destmem);
-   emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
  }
  
  /* This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to
@@@ -22463,7 -22576,7 +22577,7 @@@ expand_movmem_epilogue (rtx destmem, rt
        count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1),
                                    count, 1, OPTAB_DIRECT);
        expand_set_or_movmem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
-                                    count, QImode, 1, 4);
+                                    count, QImode, 1, 4, false);
        return;
      }
  
      }
  }
  
+ /* This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM
+    with value PROMOTED_VAL.
+    SRC is passed by pointer to be updated on return.
+    Return value is updated DST.  */
+ static rtx
+ emit_memset (rtx destmem, rtx destptr, rtx promoted_val,
+            HOST_WIDE_INT size_to_move)
+ {
+   rtx dst = destmem, adjust;
+   enum insn_code code;
+   enum machine_mode move_mode;
+   int piece_size, i;
+   /* Find the widest mode in which we could perform moves.
+      Start with the biggest power of 2 less than SIZE_TO_MOVE and half
+      it until move of such size is supported.  */
+   move_mode = GET_MODE (promoted_val);
+   if (move_mode == VOIDmode)
+     move_mode = QImode;
+   if (size_to_move < GET_MODE_SIZE (move_mode))
+     {
+       move_mode = mode_for_size (size_to_move * BITS_PER_UNIT, MODE_INT, 0);
+       promoted_val = gen_lowpart (move_mode, promoted_val);
+     }
+   piece_size = GET_MODE_SIZE (move_mode);
+   code = optab_handler (mov_optab, move_mode);
+   gcc_assert (code != CODE_FOR_nothing && promoted_val != NULL_RTX);
+   dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
+   /* Emit moves.  We'll need SIZE_TO_MOVE/PIECE_SIZES moves.  */
+   gcc_assert (size_to_move % piece_size == 0);
+   adjust = GEN_INT (piece_size);
+   for (i = 0; i < size_to_move; i += piece_size)
+     {
+       if (piece_size <= GET_MODE_SIZE (word_mode))
+       {
+         emit_insn (gen_strset (destptr, dst, promoted_val));
+         continue;
+       }
+       emit_insn (GEN_FCN (code) (dst, promoted_val));
+       emit_move_insn (destptr,
+                     gen_rtx_PLUS (Pmode, copy_rtx (destptr), adjust));
+       dst = adjust_automodify_address_nv (dst, move_mode, destptr,
+                                         piece_size);
+     }
+   /* Update DST rtx.  */
+   return dst;
+ }
  /* Output code to set at most count & (max_size - 1) bytes starting by DEST.  */
  static void
  expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
                         GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
    expand_set_or_movmem_via_loop (destmem, NULL, destptr, NULL,
                                 gen_lowpart (QImode, value), count, QImode,
-                                1, max_size / 2);
+                                1, max_size / 2, true);
  }
  
  /* Output code to set at most count & (max_size - 1) bytes starting by DEST.  */
  static void
- expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx count, int max_size)
+ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value,
+                       rtx count, int max_size)
  {
    rtx dest;
  
    if (CONST_INT_P (count))
      {
        HOST_WIDE_INT countval = INTVAL (count);
-       int offset = 0;
+       HOST_WIDE_INT epilogue_size = countval % max_size;
+       int i;
  
-       if ((countval & 0x10) && max_size > 16)
-       {
-         if (TARGET_64BIT)
-           {
-             dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset);
-             emit_insn (gen_strset (destptr, dest, value));
-             dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset + 8);
-             emit_insn (gen_strset (destptr, dest, value));
-           }
-         else
-           gcc_unreachable ();
-         offset += 16;
-       }
-       if ((countval & 0x08) && max_size > 8)
+       /* For now MAX_SIZE should be a power of 2.  This assert could be
+        relaxed, but it'll require a bit more complicated epilogue
+        expanding.  */
+       gcc_assert ((max_size & (max_size - 1)) == 0);
+       for (i = max_size; i >= 1; i >>= 1)
        {
-         if (TARGET_64BIT)
-           {
-             dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset);
-             emit_insn (gen_strset (destptr, dest, value));
-           }
-         else
+         if (epilogue_size & i)
            {
-             dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset);
-             emit_insn (gen_strset (destptr, dest, value));
-             dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset + 4);
-             emit_insn (gen_strset (destptr, dest, value));
+             if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
+               destmem = emit_memset (destmem, destptr, vec_value, i);
+             else
+               destmem = emit_memset (destmem, destptr, value, i);
            }
-         offset += 8;
-       }
-       if ((countval & 0x04) && max_size > 4)
-       {
-         dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset);
-         emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
-         offset += 4;
-       }
-       if ((countval & 0x02) && max_size > 2)
-       {
-         dest = adjust_automodify_address_nv (destmem, HImode, destptr, offset);
-         emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
-         offset += 2;
-       }
-       if ((countval & 0x01) && max_size > 1)
-       {
-         dest = adjust_automodify_address_nv (destmem, QImode, destptr, offset);
-         emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
-         offset += 1;
        }
        return;
      }
      }
  }
  
- /* Copy enough from DEST to SRC to align DEST known to by aligned by ALIGN to
-    DESIRED_ALIGNMENT.
+ /* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to
+    DESTMEM to align it to DESIRED_ALIGNMENT.  Original alignment is ALIGN.
+    Depending on ISSETMEM, either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are
+    ignored.
     Return value is updated DESTMEM.  */
  static rtx
- expand_movmem_prologue (rtx destmem, rtx srcmem,
-                       rtx destptr, rtx srcptr, rtx count,
-                       int align, int desired_alignment)
+ expand_set_or_movmem_prologue (rtx destmem, rtx srcmem,
+                                 rtx destptr, rtx srcptr, rtx value,
+                                 rtx vec_value, rtx count, int align,
+                                 int desired_alignment, bool issetmem)
  {
    int i;
    for (i = 1; i < desired_alignment; i <<= 1)
        if (align <= i)
        {
          rtx label = ix86_expand_aligntest (destptr, i, false);
-         destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
+         if (issetmem)
+           {
+             if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
+               destmem = emit_memset (destmem, destptr, vec_value, i);
+             else
+               destmem = emit_memset (destmem, destptr, value, i);
+           }
+         else
+           destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
          ix86_adjust_counter (count, i);
          emit_label (label);
          LABEL_NUSES (label) = 1;
    return destmem;
  }
  
- /* Copy enough from DST to SRC to align DST known to DESIRED_ALIGN.
-    ALIGN_BYTES is how many bytes need to be copied.
-    The function updates DST and SRC, namely, it sets proper alignment.
-    DST is returned via return value, SRC is updated via pointer SRCP.  */
- static rtx
- expand_constant_movmem_prologue (rtx dst, rtx *srcp, rtx destreg, rtx srcreg,
-                                int desired_align, int align_bytes)
- {
-   rtx src = *srcp;
-   rtx orig_dst = dst;
-   rtx orig_src = src;
-   int piece_size = 1;
-   int copied_bytes = 0;
-   int src_align_bytes = get_mem_align_offset (src, desired_align * BITS_PER_UNIT);
-   if (src_align_bytes >= 0)
-     src_align_bytes = desired_align - src_align_bytes;
+ /* Test if COUNT&SIZE is nonzero and if so, expand movme
+    or setmem sequence that is valid for SIZE..2*SIZE-1 bytes
+    and jump to DONE_LABEL.  */
+ static void
+ expand_small_movmem_or_setmem (rtx destmem, rtx srcmem,
+                              rtx destptr, rtx srcptr,
+                              rtx value, rtx vec_value,
+                              rtx count, int size,
+                              rtx done_label, bool issetmem)
+ {
+   rtx label = ix86_expand_aligntest (count, size, false);
+   enum machine_mode mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 1);
+   rtx modesize;
+   int n;
  
-   for (piece_size = 1;
-        piece_size <= desired_align && copied_bytes < align_bytes;
-        piece_size <<= 1)
+   /* If we do not have vector value to copy, we must reduce size.  */
+   if (issetmem)
      {
-       if (align_bytes & piece_size)
+       if (!vec_value)
        {
-         dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
-         copied_bytes += piece_size;
+         if (GET_MODE (value) == VOIDmode && size > 8)
+           mode = Pmode;
+         else if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (value)))
+           mode = GET_MODE (value);
        }
+       else
+       mode = GET_MODE (vec_value), value = vec_value;
      }
-   if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
-     set_mem_align (dst, desired_align * BITS_PER_UNIT);
-   if (src_align_bytes >= 0)
+   else
+     {
+       /* Choose appropriate vector mode.  */
+       if (size >= 32)
+       mode = TARGET_AVX ? V32QImode : TARGET_SSE ? V16QImode : DImode;
+       else if (size >= 16)
+       mode = TARGET_SSE ? V16QImode : DImode;
+       srcmem = change_address (srcmem, mode, srcptr);
+     }
+   destmem = change_address (destmem, mode, destptr);
+   modesize = GEN_INT (GET_MODE_SIZE (mode));
+   gcc_assert (GET_MODE_SIZE (mode) <= size);
+   for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
      {
-       unsigned int src_align;
-       for (src_align = desired_align; src_align >= 2; src_align >>= 1)
+       if (issetmem)
+       emit_move_insn (destmem, gen_lowpart (mode, value));
+       else
        {
-         if ((src_align_bytes & (src_align - 1))
-              == (align_bytes & (src_align - 1)))
-           break;
+           emit_move_insn (destmem, srcmem);
+           srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
        }
-       if (src_align > (unsigned int) desired_align)
-       src_align = desired_align;
-       if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
-       set_mem_align (src, src_align * BITS_PER_UNIT);
+       destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
      }
-   if (MEM_SIZE_KNOWN_P (orig_dst))
-     set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
-   if (MEM_SIZE_KNOWN_P (orig_src))
-     set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
-   *srcp = src;
-   return dst;
+   destmem = offset_address (destmem, count, 1);
+   destmem = offset_address (destmem, GEN_INT (-size - GET_MODE_SIZE (mode)),
+                           GET_MODE_SIZE (mode));
+   if (issetmem)
+     emit_move_insn (destmem, gen_lowpart (mode, value));
+   else
+     {
+       srcmem = offset_address (srcmem, count, 1);
+       srcmem = offset_address (srcmem, GEN_INT (-size - GET_MODE_SIZE (mode)),
+                              GET_MODE_SIZE (mode));
+       emit_move_insn (destmem, srcmem);
+     }
+   emit_jump_insn (gen_jump (done_label));
+   emit_barrier ();
+   emit_label (label);
+   LABEL_NUSES (label) = 1;
  }
  
- /* Set enough from DEST to align DEST known to by aligned by ALIGN to
-    DESIRED_ALIGNMENT.  */
+ /* Handle small memcpy (up to SIZE that is supposed to be small power of 2.
+    and get ready for the main memcpy loop by copying iniital DESIRED_ALIGN-ALIGN
+    bytes and last SIZE bytes adjusitng DESTPTR/SRCPTR/COUNT in a way we can
+    proceed with an loop copying SIZE bytes at once. Do moves in MODE.
+    DONE_LABEL is a label after the whole copying sequence. The label is created
+    on demand if *DONE_LABEL is NULL.
+    MIN_SIZE is minimal size of block copied.  This value gets adjusted for new
+    bounds after the initial copies. 
+    DESTMEM/SRCMEM are memory expressions pointing to the copies block,
+    DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether
+    we will dispatch to a library call for large blocks.
+    In pseudocode we do:
+    if (COUNT < SIZE)
+      {
+        Assume that SIZE is 4. Bigger sizes are handled analogously
+        if (COUNT & 4)
+        {
+           copy 4 bytes from SRCPTR to DESTPTR
+           copy 4 bytes from SRCPTR + COUNT - 4 to DESTPTR + COUNT - 4
+           goto done_label
+        }
+        if (!COUNT)
+        goto done_label;
+        copy 1 byte from SRCPTR to DESTPTR
+        if (COUNT & 2)
+        {
+           copy 2 bytes from SRCPTR to DESTPTR
+           copy 2 bytes from SRCPTR + COUNT - 2 to DESTPTR + COUNT - 2
+        }
+      }
+    else
+      {
+        copy at least DESIRED_ALIGN-ALIGN bytes from SRCPTR to DESTPTR
+        copy SIZE bytes from SRCPTR + COUNT - SIZE to DESTPTR + COUNT -SIZE
+        OLD_DESPTR = DESTPTR;
+        Align DESTPTR up to DESIRED_ALIGN
+        SRCPTR += DESTPTR - OLD_DESTPTR
+        COUNT -= DEST_PTR - OLD_DESTPTR
+        if (DYNAMIC_CHECK)
+        Round COUNT down to multiple of SIZE
+        << optional caller supplied zero size guard is here >>
+        << optional caller suppplied dynamic check is here >>
+        << caller supplied main copy loop is here >>
+      }
+    done_label:
+   */
  static void
- expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count,
-                       int align, int desired_alignment)
- {
-   if (align <= 1 && desired_alignment > 1)
-     {
-       rtx label = ix86_expand_aligntest (destptr, 1, false);
-       destmem = change_address (destmem, QImode, destptr);
-       emit_insn (gen_strset (destptr, destmem, gen_lowpart (QImode, value)));
-       ix86_adjust_counter (count, 1);
+ expand_set_or_movmem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
+                                                           rtx *destptr, rtx *srcptr,
+                                                           enum machine_mode mode,
+                                                           rtx value, rtx vec_value,
+                                                           rtx *count,
+                                                           rtx *done_label,
+                                                           int size,
+                                                           int desired_align,
+                                                           int align,
+                                                           unsigned HOST_WIDE_INT *min_size,
+                                                           bool dynamic_check,
+                                                           bool issetmem)
+ {
+   rtx loop_label = NULL, label;
+   int n;
+   rtx modesize;
+   int prolog_size = 0;
+   rtx mode_value;
+   /* Chose proper value to copy.  */
+   if (issetmem && VECTOR_MODE_P (mode))
+     mode_value = vec_value;
+   else
+     mode_value = value;
+   gcc_assert (GET_MODE_SIZE (mode) <= size);
+   /* See if block is big or small, handle small blocks.  */
+   if (!CONST_INT_P (*count) && *min_size < (unsigned HOST_WIDE_INT)size)
+     {
+       int size2 = size;
+       loop_label = gen_label_rtx ();
+       if (!*done_label)
+       *done_label = gen_label_rtx ();
+       emit_cmp_and_jump_insns (*count, GEN_INT (size2), GE, 0, GET_MODE (*count),
+                              1, loop_label);
+       size2 >>= 1;
+       /* Handle sizes > 3.  */
+       for (;size2 > 2; size2 >>= 1)
+       expand_small_movmem_or_setmem (destmem, srcmem,
+                                      *destptr, *srcptr,
+                                      value, vec_value,
+                                      *count,
+                                      size2, *done_label, issetmem);
+       /* Nothing to copy?  Jump to DONE_LABEL if so */
+       emit_cmp_and_jump_insns (*count, const0_rtx, EQ, 0, GET_MODE (*count),
+                              1, *done_label);
+       /* Do a byte copy.  */
+       destmem = change_address (destmem, QImode, *destptr);
+       if (issetmem)
+       emit_move_insn (destmem, gen_lowpart (QImode, value));
+       else
+       {
+           srcmem = change_address (srcmem, QImode, *srcptr);
+           emit_move_insn (destmem, srcmem);
+       }
+       /* Handle sizes 2 and 3.  */
+       label = ix86_expand_aligntest (*count, 2, false);
+       destmem = change_address (destmem, HImode, *destptr);
+       destmem = offset_address (destmem, *count, 1);
+       destmem = offset_address (destmem, GEN_INT (-2), 2);
+       if (issetmem)
+         emit_move_insn (destmem, gen_lowpart (HImode, value));
+       else
+       {
+         srcmem = change_address (srcmem, HImode, *srcptr);
+         srcmem = offset_address (srcmem, *count, 1);
+         srcmem = offset_address (srcmem, GEN_INT (-2), 2);
+         emit_move_insn (destmem, srcmem);
+       }
        emit_label (label);
        LABEL_NUSES (label) = 1;
+       emit_jump_insn (gen_jump (*done_label));
+       emit_barrier ();
      }
-   if (align <= 2 && desired_alignment > 2)
+   else
+     gcc_assert (*min_size >= (unsigned HOST_WIDE_INT)size
+               || UINTVAL (*count) >= (unsigned HOST_WIDE_INT)size);
+   /* Start memcpy for COUNT >= SIZE.  */
+   if (loop_label)
      {
-       rtx label = ix86_expand_aligntest (destptr, 2, false);
-       destmem = change_address (destmem, HImode, destptr);
-       emit_insn (gen_strset (destptr, destmem, gen_lowpart (HImode, value)));
-       ix86_adjust_counter (count, 2);
-       emit_label (label);
-       LABEL_NUSES (label) = 1;
+        emit_label (loop_label);
+        LABEL_NUSES (loop_label) = 1;
      }
-   if (align <= 4 && desired_alignment > 4)
+   /* Copy first desired_align bytes.  */
+   if (!issetmem)
+     srcmem = change_address (srcmem, mode, *srcptr);
+   destmem = change_address (destmem, mode, *destptr);
+   modesize = GEN_INT (GET_MODE_SIZE (mode));
+   for (n = 0; prolog_size < desired_align - align; n++)
      {
-       rtx label = ix86_expand_aligntest (destptr, 4, false);
-       destmem = change_address (destmem, SImode, destptr);
-       emit_insn (gen_strset (destptr, destmem, gen_lowpart (SImode, value)));
-       ix86_adjust_counter (count, 4);
-       emit_label (label);
-       LABEL_NUSES (label) = 1;
+       if (issetmem)
+         emit_move_insn (destmem, mode_value);
+       else
+       {
+           emit_move_insn (destmem, srcmem);
+           srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
+       }
+       destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
+       prolog_size += GET_MODE_SIZE (mode);
+     }
+   /* Copy last SIZE bytes.  */
+   destmem = offset_address (destmem, *count, 1);
+   destmem = offset_address (destmem,
+                           GEN_INT (-size - prolog_size),
+                           1);
+   if (issetmem)
+     emit_move_insn (destmem, mode_value);
+   else
+     {
+       srcmem = offset_address (srcmem, *count, 1);
+       srcmem = offset_address (srcmem,
+                              GEN_INT (-size - prolog_size),
+                              1);
+       emit_move_insn (destmem, srcmem);
+     }
+   for (n = 1; n * GET_MODE_SIZE (mode) < size; n++)
+     {
+       destmem = offset_address (destmem, modesize, 1);
+       if (issetmem)
+       emit_move_insn (destmem, mode_value);
+       else
+       {
+           srcmem = offset_address (srcmem, modesize, 1);
+           emit_move_insn (destmem, srcmem);
+       }
+     }
+   /* Align destination.  */
+   if (desired_align > 1 && desired_align > align)
+     {
+       rtx saveddest = *destptr;
+       gcc_assert (desired_align <= size);
+       /* Align destptr up, place it to new register.  */
+       *destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr,
+                                     GEN_INT (prolog_size),
+                                     NULL_RTX, 1, OPTAB_DIRECT);
+       *destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr,
+                                     GEN_INT (-desired_align),
+                                     *destptr, 1, OPTAB_DIRECT);
+       /* See how many bytes we skipped.  */
+       saveddest = expand_simple_binop (GET_MODE (*destptr), MINUS, saveddest,
+                                      *destptr,
+                                      saveddest, 1, OPTAB_DIRECT);
+       /* Adjust srcptr and count.  */
+       if (!issetmem)
+       *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr, saveddest,
+                                       *srcptr, 1, OPTAB_DIRECT);
+       *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
+                                   saveddest, *count, 1, OPTAB_DIRECT);
+       /* We copied at most size + prolog_size.  */
+       if (*min_size > (unsigned HOST_WIDE_INT)(size + prolog_size))
+       *min_size = (*min_size - size) & ~(unsigned HOST_WIDE_INT)(size - 1);
+       else
+       *min_size = 0;
+       /* Our loops always round down the bock size, but for dispatch to library
+        we need precise value.  */
+       if (dynamic_check)
+       *count = expand_simple_binop (GET_MODE (*count), AND, *count,
+                                     GEN_INT (-size), *count, 1, OPTAB_DIRECT);
+     }
+   else
+     {
+       gcc_assert (prolog_size == 0);
+       /* Decrease count, so we won't end up copying last word twice.  */
+       if (!CONST_INT_P (*count))
+       *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
+                                     constm1_rtx, *count, 1, OPTAB_DIRECT);
+       else
+       *count = GEN_INT ((UINTVAL (*count) - 1) & ~(unsigned HOST_WIDE_INT)(size - 1));
+       if (*min_size)
+       *min_size = (*min_size - 1) & ~(unsigned HOST_WIDE_INT)(size - 1);
      }
-   gcc_assert (desired_alignment <= 8);
  }
  
- /* Set enough from DST to align DST known to by aligned by ALIGN to
-    DESIRED_ALIGN.  ALIGN_BYTES is how many bytes need to be stored.  */
+ /* This function is like the previous one, except here we know how many bytes
+    need to be copied.  That allows us to update alignment not only of DST, which
+    is returned, but also of SRC, which is passed as a pointer for that
+    reason.  */
  static rtx
- expand_constant_setmem_prologue (rtx dst, rtx destreg, rtx value,
-                                int desired_align, int align_bytes)
+ expand_set_or_movmem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
+                                          rtx srcreg, rtx value, rtx vec_value,
+                                          int desired_align, int align_bytes,
+                                          bool issetmem)
  {
-   int off = 0;
+   rtx src = NULL;
    rtx orig_dst = dst;
-   if (align_bytes & 1)
-     {
-       dst = adjust_automodify_address_nv (dst, QImode, destreg, 0);
-       off = 1;
-       emit_insn (gen_strset (destreg, dst,
-                            gen_lowpart (QImode, value)));
-     }
-   if (align_bytes & 2)
+   rtx orig_src = NULL;
+   int piece_size = 1;
+   int copied_bytes = 0;
+   if (!issetmem)
      {
-       dst = adjust_automodify_address_nv (dst, HImode, destreg, off);
-       if (MEM_ALIGN (dst) < 2 * BITS_PER_UNIT)
-       set_mem_align (dst, 2 * BITS_PER_UNIT);
-       off = 2;
-       emit_insn (gen_strset (destreg, dst,
-                            gen_lowpart (HImode, value)));
+       gcc_assert (srcp != NULL);
+       src = *srcp;
+       orig_src = src;
      }
-   if (align_bytes & 4)
+   for (piece_size = 1;
+        piece_size <= desired_align && copied_bytes < align_bytes;
+        piece_size <<= 1)
      {
-       dst = adjust_automodify_address_nv (dst, SImode, destreg, off);
-       if (MEM_ALIGN (dst) < 4 * BITS_PER_UNIT)
-       set_mem_align (dst, 4 * BITS_PER_UNIT);
-       off = 4;
-       emit_insn (gen_strset (destreg, dst,
-                            gen_lowpart (SImode, value)));
+       if (align_bytes & piece_size)
+       {
+         if (issetmem)
+           {
+             if (vec_value && piece_size > GET_MODE_SIZE (GET_MODE (value)))
+               dst = emit_memset (dst, destreg, vec_value, piece_size);
+             else
+               dst = emit_memset (dst, destreg, value, piece_size);
+           }
+         else
+           dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
+         copied_bytes += piece_size;
+       }
      }
-   dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off);
    if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
      set_mem_align (dst, desired_align * BITS_PER_UNIT);
    if (MEM_SIZE_KNOWN_P (orig_dst))
      set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
+   if (!issetmem)
+     {
+       int src_align_bytes = get_mem_align_offset (src, desired_align
+                                                      * BITS_PER_UNIT);
+       if (src_align_bytes >= 0)
+       src_align_bytes = desired_align - src_align_bytes;
+       if (src_align_bytes >= 0)
+       {
+         unsigned int src_align;
+         for (src_align = desired_align; src_align >= 2; src_align >>= 1)
+           {
+             if ((src_align_bytes & (src_align - 1))
+                  == (align_bytes & (src_align - 1)))
+               break;
+           }
+         if (src_align > (unsigned int) desired_align)
+           src_align = desired_align;
+         if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
+           set_mem_align (src, src_align * BITS_PER_UNIT);
+       }
+       if (MEM_SIZE_KNOWN_P (orig_src))
+       set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
+       *srcp = src;
+     }
    return dst;
  }
  
- /* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation.  */
- static enum stringop_alg
- decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
          int *dynamic_check, bool *noalign)
+ /* Return true if ALG can be used in current context.  
+    Assume we expand memset if MEMSET is true.  */
+ static bool
alg_usable_p (enum stringop_alg alg, bool memset)
  {
-   const struct stringop_algs * algs;
-   bool optimize_for_speed;
+   if (alg == no_stringop)
+     return false;
+   if (alg == vector_loop)
+     return TARGET_SSE || TARGET_AVX;
    /* Algorithms using the rep prefix want at least edi and ecx;
       additionally, memset wants eax and memcpy wants esi.  Don't
       consider such algorithms if the user has appropriated those
       registers for their own purposes.        */
-   bool rep_prefix_usable = !(fixed_regs[CX_REG] || fixed_regs[DI_REG]
-                              || (memset
-                                ? fixed_regs[AX_REG] : fixed_regs[SI_REG]));
-   *noalign = false;
+   if (alg == rep_prefix_1_byte
+       || alg == rep_prefix_4_byte
+       || alg == rep_prefix_8_byte)
+     return !(fixed_regs[CX_REG] || fixed_regs[DI_REG]
+              || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG]));
+   return true;
+ }
  
- #define ALG_USABLE_P(alg) (rep_prefix_usable                  \
-                          || (alg != rep_prefix_1_byte         \
-                              && alg != rep_prefix_4_byte      \
-                              && alg != rep_prefix_8_byte))
+ /* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation.  */
+ static enum stringop_alg
+ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
+           unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size,
+           bool memset, bool zero_memset, int *dynamic_check, bool *noalign)
+ {
+   const struct stringop_algs * algs;
+   bool optimize_for_speed;
+   int max = -1;
    const struct processor_costs *cost;
+   int i;
+   bool any_alg_usable_p = false;
+   *noalign = false;
+   *dynamic_check = -1;
  
    /* Even if the string operation call is cold, we still might spend a lot
       of time processing large blocks.  */
    if (optimize_function_for_size_p (cfun)
        || (optimize_insn_for_size_p ()
-           && expected_size != -1 && expected_size < 256))
+         && (max_size < 256
+               || (expected_size != -1 && expected_size < 256))))
      optimize_for_speed = false;
    else
      optimize_for_speed = true;
  
    cost = optimize_for_speed ? ix86_cost : &ix86_size_cost;
-   *dynamic_check = -1;
    if (memset)
      algs = &cost->memset[TARGET_64BIT != 0];
    else
      algs = &cost->memcpy[TARGET_64BIT != 0];
-   if (ix86_stringop_alg != no_stringop && ALG_USABLE_P (ix86_stringop_alg))
+   /* See maximal size for user defined algorithm.  */
+   for (i = 0; i < MAX_STRINGOP_ALGS; i++)
+     {
+       enum stringop_alg candidate = algs->size[i].alg;
+       bool usable = alg_usable_p (candidate, memset);
+       any_alg_usable_p |= usable;
+       if (candidate != libcall && candidate && usable)
+         max = algs->size[i].max;
+     }
+   /* If expected size is not known but max size is small enough
+      so inline version is a win, set expected size into
+      the range.  */
+   if (max > 1 && (unsigned HOST_WIDE_INT)max >= max_size && expected_size == -1)
+     expected_size = min_size / 2 + max_size / 2;
+   /* If user specified the algorithm, honnor it if possible.  */
+   if (ix86_stringop_alg != no_stringop
+       && alg_usable_p (ix86_stringop_alg, memset))
      return ix86_stringop_alg;
    /* rep; movq or rep; movl is the smallest variant.  */
    else if (!optimize_for_speed)
      {
-       if (!count || (count & 3))
-       return rep_prefix_usable ? rep_prefix_1_byte : loop_1_byte;
+       *noalign = true;
+       if (!count || (count & 3) || (memset && !zero_memset))
+       return alg_usable_p (rep_prefix_1_byte, memset)
+              ? rep_prefix_1_byte : loop_1_byte;
        else
-       return rep_prefix_usable ? rep_prefix_4_byte : loop;
+       return alg_usable_p (rep_prefix_4_byte, memset)
+              ? rep_prefix_4_byte : loop;
      }
-   /* Very tiny blocks are best handled via the loop, REP is expensive to setup.
-    */
+   /* Very tiny blocks are best handled via the loop, REP is expensive to
+      setup.  */
    else if (expected_size != -1 && expected_size < 4)
      return loop_1_byte;
    else if (expected_size != -1)
      {
-       unsigned int i;
        enum stringop_alg alg = libcall;
+       bool alg_noalign = false;
        for (i = 0; i < MAX_STRINGOP_ALGS; i++)
        {
          /* We get here if the algorithms that were not libcall-based
            {
              enum stringop_alg candidate = algs->size[i].alg;
  
-             if (candidate != libcall && ALG_USABLE_P (candidate))
-               alg = candidate;
+             if (candidate != libcall && alg_usable_p (candidate, memset))
+               {
+                 alg = candidate;
+                 alg_noalign = algs->size[i].noalign;
+               }
              /* Honor TARGET_INLINE_ALL_STRINGOPS by picking
                 last non-libcall inline algorithm.  */
              if (TARGET_INLINE_ALL_STRINGOPS)
                     but we are still forced to inline, run the heuristic below
                     that will pick code for medium sized blocks.  */
                  if (alg != libcall)
-                   return alg;
+                   {
+                     *noalign = alg_noalign;
+                     return alg;
+                   }
                  break;
                }
-             else if (ALG_USABLE_P (candidate))
+             else if (alg_usable_p (candidate, memset))
                {
                  *noalign = algs->size[i].noalign;
                  return candidate;
                }
            }
        }
-       gcc_assert (TARGET_INLINE_ALL_STRINGOPS || !rep_prefix_usable);
      }
    /* When asked to inline the call anyway, try to pick meaningful choice.
       We look for maximal size of block that is faster to copy by hand and
       If this turns out to be bad, we might simply specify the preferred
       choice in ix86_costs.  */
    if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY)
-       && (algs->unknown_size == libcall || !ALG_USABLE_P (algs->unknown_size)))
+       && (algs->unknown_size == libcall
+         || !alg_usable_p (algs->unknown_size, memset)))
      {
-       int max = -1;
        enum stringop_alg alg;
-       int i;
-       bool any_alg_usable_p = true;
  
-       for (i = 0; i < MAX_STRINGOP_ALGS; i++)
-         {
-           enum stringop_alg candidate = algs->size[i].alg;
-           any_alg_usable_p = any_alg_usable_p && ALG_USABLE_P (candidate);
-           if (candidate != libcall && candidate
-               && ALG_USABLE_P (candidate))
-               max = algs->size[i].max;
-         }
        /* If there aren't any usable algorithms, then recursing on
           smaller sizes isn't going to find anything.  Just return the
           simple byte-at-a-time copy loop.  */
          }
        if (max == -1)
        max = 4096;
-       alg = decide_alg (count, max / 2, memset, dynamic_check, noalign);
+       alg = decide_alg (count, max / 2, min_size, max_size, memset,
+                       zero_memset, dynamic_check, noalign);
        gcc_assert (*dynamic_check == -1);
        gcc_assert (alg != libcall);
        if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
        *dynamic_check = max;
        return alg;
      }
-   return ALG_USABLE_P (algs->unknown_size) ? algs->unknown_size : libcall;
- #undef ALG_USABLE_P
+   return (alg_usable_p (algs->unknown_size, memset)
+         ? algs->unknown_size : libcall);
  }
  
  /* Decide on alignment.  We know that the operand is already aligned to ALIGN
@@@ -23013,341 -23445,6 +23446,6 @@@ decide_alignment (int align
    return desired_align;
  }
  
- /* Expand string move (memcpy) operation.  Use i386 string operations
-    when profitable.  expand_setmem contains similar code.  The code
-    depends upon architecture, block size and alignment, but always has
-    the same overall structure:
-    1) Prologue guard: Conditional that jumps up to epilogues for small
-       blocks that can be handled by epilogue alone.  This is faster
-       but also needed for correctness, since prologue assume the block
-       is larger than the desired alignment.
-       Optional dynamic check for size and libcall for large
-       blocks is emitted here too, with -minline-stringops-dynamically.
-    2) Prologue: copy first few bytes in order to get destination
-       aligned to DESIRED_ALIGN.  It is emitted only when ALIGN is less
-       than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
-       copied.  We emit either a jump tree on power of two sized
-       blocks, or a byte loop.
-    3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
-       with specified algorithm.
-    4) Epilogue: code copying tail of the block that is too small to be
-       handled by main body (or up to size guarded by prologue guard).  */
- bool
- ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
-                   rtx expected_align_exp, rtx expected_size_exp)
- {
-   rtx destreg;
-   rtx srcreg;
-   rtx label = NULL;
-   rtx tmp;
-   rtx jump_around_label = NULL;
-   HOST_WIDE_INT align = 1;
-   unsigned HOST_WIDE_INT count = 0;
-   HOST_WIDE_INT expected_size = -1;
-   int size_needed = 0, epilogue_size_needed;
-   int desired_align = 0, align_bytes = 0;
-   enum stringop_alg alg;
-   int dynamic_check;
-   bool need_zero_guard = false;
-   bool noalign;
-   enum machine_mode move_mode = VOIDmode;
-   int unroll_factor = 1;
-   if (CONST_INT_P (align_exp))
-     align = INTVAL (align_exp);
-   /* i386 can do misaligned access on reasonably increased cost.  */
-   if (CONST_INT_P (expected_align_exp)
-       && INTVAL (expected_align_exp) > align)
-     align = INTVAL (expected_align_exp);
-   /* ALIGN is the minimum of destination and source alignment, but we care here
-      just about destination alignment.  */
-   else if (MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
-     align = MEM_ALIGN (dst) / BITS_PER_UNIT;
-   if (CONST_INT_P (count_exp))
-     count = expected_size = INTVAL (count_exp);
-   if (CONST_INT_P (expected_size_exp) && count == 0)
-     expected_size = INTVAL (expected_size_exp);
-   /* Make sure we don't need to care about overflow later on.  */
-   if (count > ((unsigned HOST_WIDE_INT) 1 << 30))
-     return false;
-   /* Step 0: Decide on preferred algorithm, desired alignment and
-      size of chunks to be copied by main loop.  */
-   alg = decide_alg (count, expected_size, false, &dynamic_check, &noalign);
-   if (alg == libcall)
-     return false;
-   gcc_assert (alg != no_stringop);
-   if (!count)
-     count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
-   destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
-   srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
-   unroll_factor = 1;
-   move_mode = word_mode;
-   switch (alg)
-     {
-     case libcall:
-     case no_stringop:
-     case last_alg:
-       gcc_unreachable ();
-     case loop_1_byte:
-       need_zero_guard = true;
-       move_mode = QImode;
-       break;
-     case loop:
-       need_zero_guard = true;
-       break;
-     case unrolled_loop:
-       need_zero_guard = true;
-       unroll_factor = (TARGET_64BIT ? 4 : 2);
-       break;
-     case vector_loop:
-       need_zero_guard = true;
-       unroll_factor = 4;
-       /* Find the widest supported mode.  */
-       move_mode = word_mode;
-       while (optab_handler (mov_optab, GET_MODE_WIDER_MODE (move_mode))
-            != CODE_FOR_nothing)
-         move_mode = GET_MODE_WIDER_MODE (move_mode);
-       /* Find the corresponding vector mode with the same size as MOVE_MODE.
-        MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.).  */
-       if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
-       {
-         int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
-         move_mode = mode_for_vector (word_mode, nunits);
-         if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
-           move_mode = word_mode;
-       }
-       gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
-       break;
-     case rep_prefix_8_byte:
-       move_mode = DImode;
-       break;
-     case rep_prefix_4_byte:
-       move_mode = SImode;
-       break;
-     case rep_prefix_1_byte:
-       move_mode = QImode;
-       break;
-     }
-   size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
-   epilogue_size_needed = size_needed;
-   desired_align = decide_alignment (align, alg, expected_size, move_mode);
-   if (!TARGET_ALIGN_STRINGOPS || noalign)
-     align = desired_align;
-   /* Step 1: Prologue guard.  */
-   /* Alignment code needs count to be in register.  */
-   if (CONST_INT_P (count_exp) && desired_align > align)
-     {
-       if (INTVAL (count_exp) > desired_align
-         && INTVAL (count_exp) > size_needed)
-       {
-         align_bytes
-           = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT);
-         if (align_bytes <= 0)
-           align_bytes = 0;
-         else
-           align_bytes = desired_align - align_bytes;
-       }
-       if (align_bytes == 0)
-       count_exp = force_reg (counter_mode (count_exp), count_exp);
-     }
-   gcc_assert (desired_align >= 1 && align >= 1);
-   /* Ensure that alignment prologue won't copy past end of block.  */
-   if (size_needed > 1 || (desired_align > 1 && desired_align > align))
-     {
-       epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
-       /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
-        Make sure it is power of 2.  */
-       epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
-       if (count)
-       {
-         if (count < (unsigned HOST_WIDE_INT)epilogue_size_needed)
-           {
-             /* If main algorithm works on QImode, no epilogue is needed.
-                For small sizes just don't align anything.  */
-             if (size_needed == 1)
-               desired_align = align;
-             else
-               goto epilogue;
-           }
-       }
-       else
-       {
-         label = gen_label_rtx ();
-         emit_cmp_and_jump_insns (count_exp,
-                                  GEN_INT (epilogue_size_needed),
-                                  LTU, 0, counter_mode (count_exp), 1, label);
-         if (expected_size == -1 || expected_size < epilogue_size_needed)
-           predict_jump (REG_BR_PROB_BASE * 60 / 100);
-         else
-           predict_jump (REG_BR_PROB_BASE * 20 / 100);
-       }
-     }
-   /* Emit code to decide on runtime whether library call or inline should be
-      used.  */
-   if (dynamic_check != -1)
-     {
-       if (CONST_INT_P (count_exp))
-       {
-         if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
-           {
-             emit_block_move_via_libcall (dst, src, count_exp, false);
-             count_exp = const0_rtx;
-             goto epilogue;
-           }
-       }
-       else
-       {
-         rtx hot_label = gen_label_rtx ();
-         jump_around_label = gen_label_rtx ();
-         emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
-                                  LEU, 0, GET_MODE (count_exp), 1, hot_label);
-         predict_jump (REG_BR_PROB_BASE * 90 / 100);
-         emit_block_move_via_libcall (dst, src, count_exp, false);
-         emit_jump (jump_around_label);
-         emit_label (hot_label);
-       }
-     }
-   /* Step 2: Alignment prologue.  */
-   if (desired_align > align)
-     {
-       if (align_bytes == 0)
-       {
-         /* Except for the first move in epilogue, we no longer know
-            constant offset in aliasing info.  It don't seems to worth
-            the pain to maintain it for the first move, so throw away
-            the info early.  */
-         src = change_address (src, BLKmode, srcreg);
-         dst = change_address (dst, BLKmode, destreg);
-         dst = expand_movmem_prologue (dst, src, destreg, srcreg, count_exp, align,
-                                       desired_align);
-       }
-       else
-       {
-         /* If we know how many bytes need to be stored before dst is
-            sufficiently aligned, maintain aliasing info accurately.  */
-         dst = expand_constant_movmem_prologue (dst, &src, destreg, srcreg,
-                                                desired_align, align_bytes);
-         count_exp = plus_constant (counter_mode (count_exp),
-                                    count_exp, -align_bytes);
-         count -= align_bytes;
-       }
-       if (need_zero_guard
-         && (count < (unsigned HOST_WIDE_INT) size_needed
-             || (align_bytes == 0
-                 && count < ((unsigned HOST_WIDE_INT) size_needed
-                             + desired_align - align))))
-       {
-         /* It is possible that we copied enough so the main loop will not
-            execute.  */
-         gcc_assert (size_needed > 1);
-         if (label == NULL_RTX)
-           label = gen_label_rtx ();
-         emit_cmp_and_jump_insns (count_exp,
-                                  GEN_INT (size_needed),
-                                  LTU, 0, counter_mode (count_exp), 1, label);
-         if (expected_size == -1
-             || expected_size < (desired_align - align) / 2 + size_needed)
-           predict_jump (REG_BR_PROB_BASE * 20 / 100);
-         else
-           predict_jump (REG_BR_PROB_BASE * 60 / 100);
-       }
-     }
-   if (label && size_needed == 1)
-     {
-       emit_label (label);
-       LABEL_NUSES (label) = 1;
-       label = NULL;
-       epilogue_size_needed = 1;
-     }
-   else if (label == NULL_RTX)
-     epilogue_size_needed = size_needed;
-   /* Step 3: Main loop.  */
-   switch (alg)
-     {
-     case libcall:
-     case no_stringop:
-     case last_alg:
-       gcc_unreachable ();
-     case loop_1_byte:
-     case loop:
-     case unrolled_loop:
-     case vector_loop:
-       expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, NULL,
-                                    count_exp, move_mode, unroll_factor,
-                                    expected_size);
-       break;
-     case rep_prefix_8_byte:
-     case rep_prefix_4_byte:
-     case rep_prefix_1_byte:
-       expand_movmem_via_rep_mov (dst, src, destreg, srcreg, count_exp,
-                                move_mode);
-       break;
-     }
-   /* Adjust properly the offset of src and dest memory for aliasing.  */
-   if (CONST_INT_P (count_exp))
-     {
-       src = adjust_automodify_address_nv (src, BLKmode, srcreg,
-                                         (count / size_needed) * size_needed);
-       dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
-                                         (count / size_needed) * size_needed);
-     }
-   else
-     {
-       src = change_address (src, BLKmode, srcreg);
-       dst = change_address (dst, BLKmode, destreg);
-     }
-   /* Step 4: Epilogue to copy the remaining bytes.  */
-  epilogue:
-   if (label)
-     {
-       /* When the main loop is done, COUNT_EXP might hold original count,
-        while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
-        Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
-        bytes. Compensate if needed.  */
-       if (size_needed < epilogue_size_needed)
-       {
-         tmp =
-           expand_simple_binop (counter_mode (count_exp), AND, count_exp,
-                                GEN_INT (size_needed - 1), count_exp, 1,
-                                OPTAB_DIRECT);
-         if (tmp != count_exp)
-           emit_move_insn (count_exp, tmp);
-       }
-       emit_label (label);
-       LABEL_NUSES (label) = 1;
-     }
-   if (count_exp != const0_rtx && epilogue_size_needed > 1)
-     expand_movmem_epilogue (dst, src, destreg, srcreg, count_exp,
-                           epilogue_size_needed);
-   if (jump_around_label)
-     emit_label (jump_around_label);
-   return true;
- }
  
  /* Helper function for memcpy.  For QImode value 0xXY produce
     0xXYXYXYXY of wide specified by MODE.  This is essentially
@@@ -23361,9 -23458,9 +23459,9 @@@ promote_duplicated_reg (enum machine_mo
    rtx tmp;
    int nops = mode == DImode ? 3 : 2;
  
-   gcc_assert (mode == SImode || mode == DImode);
+   gcc_assert (mode == SImode || mode == DImode || val == const0_rtx);
    if (val == const0_rtx)
-     return copy_to_mode_reg (mode, const0_rtx);
+     return copy_to_mode_reg (mode, CONST0_RTX (mode));
    if (CONST_INT_P (val))
      {
        HOST_WIDE_INT v = INTVAL (val) & 255;
     be needed by main loop copying SIZE_NEEDED chunks and prologue getting
     alignment from ALIGN to DESIRED_ALIGN.  */
  static rtx
- promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align, int align)
+ promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align,
+                               int align)
  {
    rtx promoted_val;
  
    return promoted_val;
  }
  
- /* Expand string clear operation (bzero).  Use i386 string operations when
-    profitable.  See expand_movmem comment for explanation of individual
-    steps performed.  */
- bool
- ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
-                   rtx expected_align_exp, rtx expected_size_exp)
+ /* Expand string move (memcpy) ot store (memset) operation.  Use i386 string
+    operations when profitable.  The code depends upon architecture, block size
+    and alignment, but always has one of the following overall structures:
+    Aligned move sequence:
+      1) Prologue guard: Conditional that jumps up to epilogues for small
+       blocks that can be handled by epilogue alone.  This is faster
+       but also needed for correctness, since prologue assume the block
+       is larger than the desired alignment.
+       Optional dynamic check for size and libcall for large
+       blocks is emitted here too, with -minline-stringops-dynamically.
+      2) Prologue: copy first few bytes in order to get destination
+       aligned to DESIRED_ALIGN.  It is emitted only when ALIGN is less
+       than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
+       copied.  We emit either a jump tree on power of two sized
+       blocks, or a byte loop.
+      3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
+       with specified algorithm.
+      4) Epilogue: code copying tail of the block that is too small to be
+       handled by main body (or up to size guarded by prologue guard). 
+   Misaligned move sequence
+      1) missaligned move prologue/epilogue containing:
+         a) Prologue handling small memory blocks and jumping to done_label
+          (skipped if blocks are known to be large enough)
+       b) Signle move copying first DESIRED_ALIGN-ALIGN bytes if alignment is
+            needed by single possibly misaligned move
+          (skipped if alignment is not needed)
+         c) Copy of last SIZE_NEEDED bytes by possibly misaligned moves
+      2) Zero size guard dispatching to done_label, if needed
+      3) dispatch to library call, if needed,
+      3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
+       with specified algorithm.  */
+ static bool
+ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
+                             rtx align_exp, rtx expected_align_exp,
+                             rtx expected_size_exp, bool issetmem)
  {
    rtx destreg;
+   rtx srcreg = NULL;
    rtx label = NULL;
    rtx tmp;
    rtx jump_around_label = NULL;
    int desired_align = 0, align_bytes = 0;
    enum stringop_alg alg;
    rtx promoted_val = NULL;
+   rtx vec_promoted_val = NULL;
    bool force_loopy_epilogue = false;
    int dynamic_check;
    bool need_zero_guard = false;
    bool noalign;
    enum machine_mode move_mode = VOIDmode;
-   int unroll_factor;
+   int unroll_factor = 1;
+   /* TODO: Once vlaue ranges are available, fill in proper data.  */
+   unsigned HOST_WIDE_INT min_size = 0;
+   unsigned HOST_WIDE_INT max_size = -1;
+   bool misaligned_prologue_used = false;
  
    if (CONST_INT_P (align_exp))
      align = INTVAL (align_exp);
    if (CONST_INT_P (expected_align_exp)
        && INTVAL (expected_align_exp) > align)
      align = INTVAL (expected_align_exp);
+   /* ALIGN is the minimum of destination and source alignment, but we care here
+      just about destination alignment.  */
+   else if (!issetmem
+          && MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
+     align = MEM_ALIGN (dst) / BITS_PER_UNIT;
    if (CONST_INT_P (count_exp))
-     count = expected_size = INTVAL (count_exp);
+     min_size = max_size = count = expected_size = INTVAL (count_exp);
    if (CONST_INT_P (expected_size_exp) && count == 0)
      expected_size = INTVAL (expected_size_exp);
  
  
    /* Step 0: Decide on preferred algorithm, desired alignment and
       size of chunks to be copied by main loop.  */
-   alg = decide_alg (count, expected_size, true, &dynamic_check, &noalign);
+   alg = decide_alg (count, expected_size, min_size, max_size, issetmem,
+                   issetmem && val_exp == const0_rtx,
+                   &dynamic_check, &noalign);
    if (alg == libcall)
      return false;
    gcc_assert (alg != no_stringop);
  
+   /* For now vector-version of memset is generated only for memory zeroing, as
+      creating of promoted vector value is very cheap in this case.  */
+   if (issetmem && alg == vector_loop && val_exp != const0_rtx)
+     alg = unrolled_loop;
    if (!count)
-     count_exp = copy_to_mode_reg (counter_mode (count_exp), count_exp);
+     count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
    destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
+   if (!issetmem)
+     srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
  
-   move_mode = word_mode;
    unroll_factor = 1;
+   move_mode = word_mode;
    switch (alg)
      {
      case libcall:
      case no_stringop:
      case last_alg:
        gcc_unreachable ();
+     case loop_1_byte:
+       need_zero_guard = true;
+       move_mode = QImode;
+       break;
      case loop:
        need_zero_guard = true;
        break;
-     case vector_loop:
      case unrolled_loop:
+       need_zero_guard = true;
+       unroll_factor = (TARGET_64BIT ? 4 : 2);
+       break;
+     case vector_loop:
        need_zero_guard = true;
        unroll_factor = 4;
+       /* Find the widest supported mode.  */
+       move_mode = word_mode;
+       while (optab_handler (mov_optab, GET_MODE_WIDER_MODE (move_mode))
+            != CODE_FOR_nothing)
+         move_mode = GET_MODE_WIDER_MODE (move_mode);
+       /* Find the corresponding vector mode with the same size as MOVE_MODE.
+        MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.).  */
+       if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
+       {
+         int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
+         move_mode = mode_for_vector (word_mode, nunits);
+         if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
+           move_mode = word_mode;
+       }
+       gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
        break;
      case rep_prefix_8_byte:
        move_mode = DImode;
      case rep_prefix_1_byte:
        move_mode = QImode;
        break;
-     case loop_1_byte:
-       need_zero_guard = true;
-       move_mode = QImode;
-       break;
      }
    size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
    epilogue_size_needed = size_needed;
            align_bytes = desired_align - align_bytes;
        }
        if (align_bytes == 0)
-       {
-         enum machine_mode mode = SImode;
-         if (TARGET_64BIT && (count & ~0xffffffff))
-           mode = DImode;
-         count_exp = force_reg (mode, count_exp);
-       }
+       count_exp = force_reg (counter_mode (count_exp), count_exp);
      }
+   gcc_assert (desired_align >= 1 && align >= 1);
+   /* Misaligned move sequences handles both prologues and epilogues at once.
+      Default code generation results in smaller code for large alignments and
+      also avoids redundant job when sizes are known precisely.  */
+   misaligned_prologue_used = (TARGET_MISALIGNED_MOVE_STRING_PROLOGUES
+                             && MAX (desired_align, epilogue_size_needed) <= 32
+                             && ((desired_align > align && !align_bytes)
+                                 || (!count && epilogue_size_needed > 1)));
    /* Do the cheap promotion to allow better CSE across the
       main loop and epilogue (ie one load of the big constant in the
-      front of all code.  */
-   if (CONST_INT_P (val_exp))
-     promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
-                                                  desired_align, align);
+      front of all code.  
+      For now the misaligned move sequences do not have fast path
+      without broadcasting.  */
+   if (issetmem && ((CONST_INT_P (val_exp) || misaligned_prologue_used)))
+     {
+       if (alg == vector_loop)
+       {
+         gcc_assert (val_exp == const0_rtx);
+         vec_promoted_val = promote_duplicated_reg (move_mode, val_exp);
+         promoted_val = promote_duplicated_reg_to_size (val_exp,
+                                                        GET_MODE_SIZE (word_mode),
+                                                        desired_align, align);
+       }
+       else
+       {
+         promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
+                                                        desired_align, align);
+       }
+     }
+   /* Misaligned move sequences handles both prologues and epilogues at once.
+      Default code generation results in smaller code for large alignments and
+      also avoids redundant job when sizes are known precisely.  */
+   if (misaligned_prologue_used)
+     {
+       /* Misaligned move prologue handled small blocks by itself.  */
+       misaligned_prologue_used = true;
+       expand_set_or_movmem_prologue_epilogue_by_misaligned_moves
+          (dst, src, &destreg, &srcreg,
+           move_mode, promoted_val, vec_promoted_val,
+           &count_exp,
+           &jump_around_label,
+             desired_align < align
+           ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed,
+           desired_align, align, &min_size, dynamic_check, issetmem);
+       if (!issetmem)
+         src = change_address (src, BLKmode, srcreg);
+       dst = change_address (dst, BLKmode, destreg);
+       set_mem_align (dst, desired_align * BITS_PER_UNIT);
+       epilogue_size_needed = 0;
+       if (need_zero_guard && !min_size)
+       {
+         /* It is possible that we copied enough so the main loop will not
+            execute.  */
+         gcc_assert (size_needed > 1);
+         if (jump_around_label == NULL_RTX)
+           jump_around_label = gen_label_rtx ();
+         emit_cmp_and_jump_insns (count_exp,
+                                  GEN_INT (size_needed),
+                                  LTU, 0, counter_mode (count_exp), 1, jump_around_label);
+         if (expected_size == -1
+             || expected_size < (desired_align - align) / 2 + size_needed)
+           predict_jump (REG_BR_PROB_BASE * 20 / 100);
+         else
+           predict_jump (REG_BR_PROB_BASE * 60 / 100);
+       }
+     }
    /* Ensure that alignment prologue won't copy past end of block.  */
-   if (size_needed > 1 || (desired_align > 1 && desired_align > align))
+   else if (size_needed > 1 || (desired_align > 1 && desired_align > align))
      {
        epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
-       /* Epilogue always copies COUNT_EXP & (EPILOGUE_SIZE_NEEDED - 1) bytes.
+       /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
         Make sure it is power of 2.  */
        epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
  
         promoting mode.  This mean that if the promoted VAL is not constant,
         we might not use it in the epilogue and have to use byte
         loop variant.  */
-       if (epilogue_size_needed > 2 && !promoted_val)
-         force_loopy_epilogue = true;
+       if (issetmem && epilogue_size_needed > 2 && !promoted_val)
+       force_loopy_epilogue = true;
        if (count)
        {
          if (count < (unsigned HOST_WIDE_INT)epilogue_size_needed)
                goto epilogue;
            }
        }
-       else
+       else if (min_size < (unsigned HOST_WIDE_INT)epilogue_size_needed)
        {
+         gcc_assert (max_size >= (unsigned HOST_WIDE_INT)epilogue_size_needed);
          label = gen_label_rtx ();
          emit_cmp_and_jump_insns (count_exp,
                                   GEN_INT (epilogue_size_needed),
                                   LTU, 0, counter_mode (count_exp), 1, label);
-         if (expected_size == -1 || expected_size <= epilogue_size_needed)
+         if (expected_size == -1 || expected_size < epilogue_size_needed)
            predict_jump (REG_BR_PROB_BASE * 60 / 100);
          else
            predict_jump (REG_BR_PROB_BASE * 20 / 100);
        }
      }
+   /* Emit code to decide on runtime whether library call or inline should be
+      used.  */
    if (dynamic_check != -1)
      {
-       rtx hot_label = gen_label_rtx ();
-       jump_around_label = gen_label_rtx ();
-       emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
-                              LEU, 0, counter_mode (count_exp), 1, hot_label);
-       predict_jump (REG_BR_PROB_BASE * 90 / 100);
-       set_storage_via_libcall (dst, count_exp, val_exp, false);
-       emit_jump (jump_around_label);
-       emit_label (hot_label);
+       if (!issetmem && CONST_INT_P (count_exp))
+       {
+         if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
+           {
+             emit_block_move_via_libcall (dst, src, count_exp, false);
+             count_exp = const0_rtx;
+             goto epilogue;
+           }
+       }
+       else
+       {
+         rtx hot_label = gen_label_rtx ();
+         jump_around_label = gen_label_rtx ();
+         emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
+                                  LEU, 0, GET_MODE (count_exp), 1, hot_label);
+         predict_jump (REG_BR_PROB_BASE * 90 / 100);
+         if (issetmem)
+           set_storage_via_libcall (dst, count_exp, val_exp, false);
+         else
+           emit_block_move_via_libcall (dst, src, count_exp, false);
+         emit_jump (jump_around_label);
+         emit_label (hot_label);
+       }
      }
  
    /* Step 2: Alignment prologue.  */
    /* Do the expensive promotion once we branched off the small blocks.  */
-   if (!promoted_val)
+   if (issetmem && !promoted_val)
      promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
                                                   desired_align, align);
-   gcc_assert (desired_align >= 1 && align >= 1);
  
-   if (desired_align > align)
+   if (desired_align > align && !misaligned_prologue_used)
      {
        if (align_bytes == 0)
        {
-         /* Except for the first move in epilogue, we no longer know
+         /* Except for the first move in prologue, we no longer know
             constant offset in aliasing info.  It don't seems to worth
             the pain to maintain it for the first move, so throw away
             the info early.  */
          dst = change_address (dst, BLKmode, destreg);
-         expand_setmem_prologue (dst, destreg, promoted_val, count_exp, align,
-                                 desired_align);
+         if (!issetmem)
+           src = change_address (src, BLKmode, srcreg);
+         dst = expand_set_or_movmem_prologue (dst, src, destreg, srcreg,
+                                           promoted_val, vec_promoted_val,
+                                           count_exp, align, desired_align,
+                                           issetmem);
+         /* At most desired_align - align bytes are copied.  */
+         if (min_size < (unsigned)(desired_align - align))
+           min_size = 0;
+         else
+           min_size -= desired_align - align;
        }
        else
        {
          /* If we know how many bytes need to be stored before dst is
             sufficiently aligned, maintain aliasing info accurately.  */
-         dst = expand_constant_setmem_prologue (dst, destreg, promoted_val,
-                                                desired_align, align_bytes);
+         dst = expand_set_or_movmem_constant_prologue (dst, &src, destreg,
+                                                          srcreg,
+                                                          promoted_val,
+                                                          vec_promoted_val,
+                                                          desired_align,
+                                                          align_bytes,
+                                                          issetmem);
          count_exp = plus_constant (counter_mode (count_exp),
                                     count_exp, -align_bytes);
          count -= align_bytes;
+         min_size -= align_bytes;
+         max_size -= align_bytes;
        }
        if (need_zero_guard
+         && !min_size
          && (count < (unsigned HOST_WIDE_INT) size_needed
              || (align_bytes == 0
                  && count < ((unsigned HOST_WIDE_INT) size_needed
        emit_label (label);
        LABEL_NUSES (label) = 1;
        label = NULL;
-       promoted_val = val_exp;
        epilogue_size_needed = 1;
+       if (issetmem)
+       promoted_val = val_exp;
      }
-   else if (label == NULL_RTX)
+   else if (label == NULL_RTX && !misaligned_prologue_used)
      epilogue_size_needed = size_needed;
  
    /* Step 3: Main loop.  */
        gcc_unreachable ();
      case loop_1_byte:
      case loop:
-     case vector_loop:
      case unrolled_loop:
-       expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, promoted_val,
+       expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, promoted_val,
                                     count_exp, move_mode, unroll_factor,
-                                    expected_size);
+                                    expected_size, issetmem);
        break;
-     case rep_prefix_8_byte:
-       expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
-                                 DImode, val_exp);
+     case vector_loop:
+       expand_set_or_movmem_via_loop (dst, src, destreg, srcreg,
+                                    vec_promoted_val, count_exp, move_mode,
+                                    unroll_factor, expected_size, issetmem);
        break;
+     case rep_prefix_8_byte:
      case rep_prefix_4_byte:
-       expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
-                                 SImode, val_exp);
-       break;
      case rep_prefix_1_byte:
-       expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
-                                 QImode, val_exp);
+       expand_set_or_movmem_via_rep (dst, src, destreg, srcreg, promoted_val,
+                                      val_exp, count_exp, move_mode, issetmem);
        break;
      }
    /* Adjust properly the offset of src and dest memory for aliasing.  */
    if (CONST_INT_P (count_exp))
-     dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
-                                       (count / size_needed) * size_needed);
+     {
+       if (!issetmem)
+       src = adjust_automodify_address_nv (src, BLKmode, srcreg,
+                                           (count / size_needed) * size_needed);
+       dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
+                                         (count / size_needed) * size_needed);
+     }
    else
-     dst = change_address (dst, BLKmode, destreg);
+     {
+       if (!issetmem)
+       src = change_address (src, BLKmode, srcreg);
+       dst = change_address (dst, BLKmode, destreg);
+     }
  
    /* Step 4: Epilogue to copy the remaining bytes.  */
+  epilogue:
    if (label)
      {
        /* When the main loop is done, COUNT_EXP might hold original count,
-        while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
+        while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
         Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
         bytes. Compensate if needed.  */
  
        emit_label (label);
        LABEL_NUSES (label) = 1;
      }
-  epilogue:
    if (count_exp != const0_rtx && epilogue_size_needed > 1)
      {
        if (force_loopy_epilogue)
        expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
                                         epilogue_size_needed);
        else
-       expand_setmem_epilogue (dst, destreg, promoted_val, count_exp,
-                               epilogue_size_needed);
+       {
+         if (issetmem)
+           expand_setmem_epilogue (dst, destreg, promoted_val,
+                                   vec_promoted_val, count_exp,
+                                   epilogue_size_needed);
+         else
+           expand_movmem_epilogue (dst, src, destreg, srcreg, count_exp,
+                                   epilogue_size_needed);
+       }
      }
    if (jump_around_label)
      emit_label (jump_around_label);
    return true;
  }
  
+ /* Wrapper for ix86_expand_set_or_movmem for memcpy case.  */
+ bool
+ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
+                   rtx expected_align_exp, rtx expected_size_exp)
+ {
+   return ix86_expand_set_or_movmem (dst, src, count_exp, NULL, align_exp,
+                   expected_align_exp, expected_size_exp, false);
+ }
+ /* Wrapper for ix86_expand_set_or_movmem for memset case.  */
+ bool
+ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
+                   rtx expected_align_exp, rtx expected_size_exp)
+ {
+   return ix86_expand_set_or_movmem (dst, NULL, count_exp, val_exp, align_exp,
+                     expected_align_exp, expected_size_exp, true);
+ }
  /* Expand the appropriate insns for doing strlen if not just doing
     repnz; scasb
  
@@@ -24108,13 -24411,13 +24412,13 @@@ ix86_output_call_insn (rtx insn, rtx ca
    if (SIBLING_CALL_P (insn))
      {
        if (direct_p)
-       xasm = "jmp\t%P0";
+       xasm = "%!jmp\t%P0";
        /* SEH epilogue detection requires the indirect branch case
         to include REX.W.  */
        else if (TARGET_SEH)
-       xasm = "rex.W jmp %A0";
+       xasm = "%!rex.W jmp %A0";
        else
-       xasm = "jmp\t%A0";
+       xasm = "%!jmp\t%A0";
  
        output_asm_insn (xasm, &call_op);
        return "";
      }
  
    if (direct_p)
-     xasm = "call\t%P0";
+     xasm = "%!call\t%P0";
    else
-     xasm = "call\t%A0";
+     xasm = "%!call\t%A0";
  
    output_asm_insn (xasm, &call_op);
  
@@@ -25596,7 -25899,8 +25900,7 @@@ ix86_data_alignment (tree type, int ali
        && AGGREGATE_TYPE_P (type)
        && TYPE_SIZE (type)
        && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
 -      && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= (unsigned) max_align
 -        || TREE_INT_CST_HIGH (TYPE_SIZE (type)))
 +      && wi::geu_p (TYPE_SIZE (type), max_align)
        && align < max_align)
      align = max_align;
  
        if ((opt ? AGGREGATE_TYPE_P (type) : TREE_CODE (type) == ARRAY_TYPE)
          && TYPE_SIZE (type)
          && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
 -        && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 128
 -            || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 128)
 +        && wi::geu_p (TYPE_SIZE (type), 128)
 +        && align < 128)
        return 128;
      }
  
@@@ -25717,13 -26021,13 +26021,13 @@@ ix86_local_alignment (tree exp, enum ma
        && TARGET_SSE)
      {
        if (AGGREGATE_TYPE_P (type)
 -         && (va_list_type_node == NULL_TREE
 -             || (TYPE_MAIN_VARIANT (type)
 -                 != TYPE_MAIN_VARIANT (va_list_type_node)))
 -         && TYPE_SIZE (type)
 -         && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
 -         && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 16
 -             || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 128)
 +        && (va_list_type_node == NULL_TREE
 +            || (TYPE_MAIN_VARIANT (type)
 +                != TYPE_MAIN_VARIANT (va_list_type_node)))
 +        && TYPE_SIZE (type)
 +        && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
 +        && wi::geu_p (TYPE_SIZE (type), 16)
 +        && align < 128)
        return 128;
      }
    if (TREE_CODE (type) == ARRAY_TYPE)
@@@ -28743,7 -29047,7 +29047,7 @@@ ix86_builtin_tm_load (tree type
  {
    if (TREE_CODE (type) == VECTOR_TYPE)
      {
 -      switch (tree_low_cst (TYPE_SIZE (type), 1))
 +      switch (tree_to_uhwi (TYPE_SIZE (type)))
        {
        case 64:
          return builtin_decl_explicit (BUILT_IN_TM_LOAD_M64);
@@@ -28763,7 -29067,7 +29067,7 @@@ ix86_builtin_tm_store (tree type
  {
    if (TREE_CODE (type) == VECTOR_TYPE)
      {
 -      switch (tree_low_cst (TYPE_SIZE (type), 1))
 +      switch (tree_to_uhwi (TYPE_SIZE (type)))
        {
        case 64:
          return builtin_decl_explicit (BUILT_IN_TM_STORE_M64);
@@@ -29940,7 -30244,7 +30244,7 @@@ ix86_get_function_versions_dispatcher (
    while (default_version_info != NULL)
      {
        if (is_function_default_version
-           (default_version_info->this_node->symbol.decl))
+           (default_version_info->this_node->decl))
          break;
        default_version_info = default_version_info->next;
      }
        struct cgraph_function_version_info *dispatcher_version_info = NULL;
  
        /* Right now, the dispatching is done via ifunc.  */
-       dispatch_decl = make_dispatcher_decl (default_node->symbol.decl);
+       dispatch_decl = make_dispatcher_decl (default_node->decl);
  
        dispatcher_node = cgraph_get_create_node (dispatch_decl);
        gcc_assert (dispatcher_node != NULL);
        dispatcher_version_info
        = insert_new_cgraph_node_version (dispatcher_node);
        dispatcher_version_info->next = default_version_info;
-       dispatcher_node->symbol.definition = 1;
+       dispatcher_node->definition = 1;
  
        /* Set the dispatcher for all the versions.  */
        it_v = default_version_info;
    else
  #endif
      {
-       error_at (DECL_SOURCE_LOCATION (default_node->symbol.decl),
+       error_at (DECL_SOURCE_LOCATION (default_node->decl),
                "multiversioning needs ifunc which is not supported "
                "on this target");
      }
@@@ -30130,13 -30434,13 +30434,13 @@@ ix86_generate_version_dispatcher_body (
      return node_version_info->dispatcher_resolver;
  
    /* The first version in the chain corresponds to the default version.  */
-   default_ver_decl = node_version_info->next->this_node->symbol.decl;
+   default_ver_decl = node_version_info->next->this_node->decl;
  
    /* node is going to be an alias, so remove the finalized bit.  */
-   node->symbol.definition = false;
+   node->definition = false;
  
    resolver_decl = make_resolver_func (default_ver_decl,
-                                     node->symbol.decl, &empty_bb);
+                                     node->decl, &empty_bb);
  
    node_version_info->dispatcher_resolver = resolver_decl;
  
         not.  This happens for methods in derived classes that override
         virtual methods in base classes but are not explicitly marked as
         virtual.  */
-       if (DECL_VINDEX (versn->symbol.decl))
+       if (DECL_VINDEX (versn->decl))
        sorry ("Virtual function multiversioning not supported");
  
-       fn_ver_vec.safe_push (versn->symbol.decl);
+       fn_ver_vec.safe_push (versn->decl);
      }
  
    dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb);
@@@ -31703,8 -32007,8 +32007,8 @@@ ix86_expand_args_builtin (const struct 
      }
    else
      {
-       target = gen_reg_rtx (rmode);
-       real_target = simplify_gen_subreg (tmode, target, rmode, 0);
+       real_target = gen_reg_rtx (tmode);
+       target = simplify_gen_subreg (rmode, real_target, tmode, 0);
      }
  
    for (i = 0; i < nargs; i++)
@@@ -32077,8 -32381,8 +32381,8 @@@ get_element_number (tree vec_type, tre
  {
    unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
  
 -  if (!host_integerp (arg, 1)
 -      || (elt = tree_low_cst (arg, 1), elt > max))
 +  if (!tree_fits_uhwi_p (arg)
 +      || (elt = tree_to_uhwi (arg), elt > max))
      {
        error ("selector must be an integer constant in the range 0..%wi", max);
        return 0;
@@@ -34143,6 -34447,7 +34447,7 @@@ ix86_class_likely_spilled_p (reg_class_
        case SSE_FIRST_REG:
        case FP_TOP_REG:
        case FP_SECOND_REG:
+       case BND_REGS:
        return true;
  
        default:
@@@ -34491,6 -34796,8 +34796,8 @@@ ix86_hard_regno_mode_ok (int regno, enu
      return VALID_FP_MODE_P (mode);
    if (MASK_REGNO_P (regno))
      return VALID_MASK_REG_MODE (mode);
+   if (BND_REGNO_P (regno))
+     return VALID_BND_REG_MODE (mode);
    if (SSE_REGNO_P (regno))
      {
        /* We implement the move patterns for all vector modes into and
@@@ -35304,6 -35611,10 +35611,10 @@@ x86_order_regs_for_local_alloc (void
     for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++)
       reg_alloc_order [pos++] = i;
  
+    /* MPX bound registers.  */
+    for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++)
+      reg_alloc_order [pos++] = i;
     /* x87 registers.  */
     if (TARGET_SSE_MATH)
       for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
@@@ -36420,8 -36731,9 +36731,9 @@@ ix86_expand_vector_init_duplicate (boo
          emit_move_insn (tmp1, gen_lowpart (SImode, val));
  
          /* Insert the SImode value as low element of a V4SImode vector. */
-         tmp2 = gen_lowpart (V4SImode, dperm.op0);
+         tmp2 = gen_reg_rtx (V4SImode);
          emit_insn (gen_vec_setv4si_0 (tmp2, CONST0_RTX (V4SImode), tmp1));
+         emit_move_insn (dperm.op0, gen_lowpart (mode, tmp2));
  
          ok = (expand_vec_perm_1 (&dperm)
                || expand_vec_perm_broadcast_1 (&dperm));
                                 NULL_RTX, 1, OPTAB_LIB_WIDEN);
        val = expand_simple_binop (wsmode, IOR, val, x, x, 1, OPTAB_LIB_WIDEN);
  
-       x = gen_lowpart (wvmode, target);
+       x = gen_reg_rtx (wvmode);
        ok = ix86_expand_vector_init_duplicate (mmx_ok, wvmode, x, val);
        gcc_assert (ok);
+       emit_move_insn (target, gen_lowpart (GET_MODE (target), x));
        return ok;
        }
  
@@@ -37328,8 -37641,9 +37641,9 @@@ ix86_expand_vector_set (bool mmx_ok, rt
        else
        {
          /* For SSE1, we have to reuse the V4SF code.  */
-         ix86_expand_vector_set (false, gen_lowpart (V4SFmode, target),
-                                 gen_lowpart (SFmode, val), elt);
+         rtx t = gen_reg_rtx (V4SFmode);
+         ix86_expand_vector_set (false, t, gen_lowpart (SFmode, val), elt);
+         emit_move_insn (target, gen_lowpart (mode, t));
        }
        return;
  
@@@ -37647,7 -37961,7 +37961,7 @@@ ix86_expand_vector_extract (bool mmx_ok
  static void
  emit_reduc_half (rtx dest, rtx src, int i)
  {
-   rtx tem;
+   rtx tem, d = dest;
    switch (GET_MODE (src))
      {
      case V4SFmode:
      case V8HImode:
      case V4SImode:
      case V2DImode:
-       tem = gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, dest),
-                               gen_lowpart (V1TImode, src),
+       d = gen_reg_rtx (V1TImode);
+       tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src),
                                GEN_INT (i / 2));
        break;
      case V8SFmode:
      case V8SImode:
      case V4DImode:
        if (i == 256)
-       tem = gen_avx2_permv2ti (gen_lowpart (V4DImode, dest),
-                                gen_lowpart (V4DImode, src),
-                                gen_lowpart (V4DImode, src),
-                                const1_rtx);
+       {
+         if (GET_MODE (dest) != V4DImode)
+           d = gen_reg_rtx (V4DImode);
+         tem = gen_avx2_permv2ti (d, gen_lowpart (V4DImode, src),
+                                  gen_lowpart (V4DImode, src),
+                                  const1_rtx);
+       }
        else
-       tem = gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, dest),
-                                 gen_lowpart (V2TImode, src),
-                                 GEN_INT (i / 2));
+       {
+         d = gen_reg_rtx (V2TImode);
+         tem = gen_avx2_lshrv2ti3 (d, gen_lowpart (V2TImode, src),
+                                   GEN_INT (i / 2));
+       }
        break;
      default:
        gcc_unreachable ();
      }
    emit_insn (tem);
+   if (d != dest)
+     emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
  }
  
  /* Expand a vector reduction.  FN is the binary pattern to reduce;
@@@ -38109,7 -38430,7 +38430,7 @@@ void ix86_emit_swsqrtsf (rtx res, rtx a
    e2 = gen_reg_rtx (mode);
    e3 = gen_reg_rtx (mode);
  
 -  real_from_integer (&r, VOIDmode, -3, -1, 0);
 +  real_from_integer (&r, VOIDmode, -3, SIGNED);
    mthree = CONST_DOUBLE_FROM_REAL_VALUE (r, SFmode);
  
    real_arithmetic (&r, NEGATE_EXPR, &dconsthalf, NULL);
@@@ -39191,6 -39512,8 +39512,8 @@@ expand_vec_perm_blend (struct expand_ve
              emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm));
            else
              emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm));
+           if (target != d->target)
+             emit_move_insn (d->target, gen_lowpart (d->vmode, target));
            return true;
          }
  
        /* FALLTHRU */
  
      do_subreg:
-       target = gen_lowpart (vmode, target);
+       target = gen_reg_rtx (vmode);
        op0 = gen_lowpart (vmode, op0);
        op1 = gen_lowpart (vmode, op1);
        break;
  
                vmode = V32QImode;
                nelt = 32;
-               target = gen_lowpart (vmode, target);
+               target = gen_reg_rtx (vmode);
                op0 = gen_lowpart (vmode, op0);
                op1 = gen_lowpart (vmode, op1);
                goto finish_pblendvb;
    x = gen_rtx_VEC_MERGE (vmode, op1, op0, GEN_INT (mask));
    x = gen_rtx_SET (VOIDmode, target, x);
    emit_insn (x);
+   if (target != d->target)
+     emit_move_insn (d->target, gen_lowpart (d->vmode, target));
  
    return true;
  }
@@@ -39392,13 -39717,17 +39717,17 @@@ expand_vec_perm_pshufb (struct expand_v
  
              /* Use vperm2i128 insn.  The pattern uses
                 V4DImode instead of V2TImode.  */
-             target = gen_lowpart (V4DImode, d->target);
+             target = d->target;
+             if (d->vmode != V4DImode)
+               target = gen_reg_rtx (V4DImode);
              op0 = gen_lowpart (V4DImode, d->op0);
              op1 = gen_lowpart (V4DImode, d->op1);
              rperm[0]
                = GEN_INT (((d->perm[0] & (nelt / 2)) ? 1 : 0)
                           || ((d->perm[nelt / 2] & (nelt / 2)) ? 2 : 0));
              emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0]));
+             if (target != d->target)
+               emit_move_insn (d->target, gen_lowpart (d->vmode, target));
              return true;
            }
          return false;
                    perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3;
                  if (d->testing_p)
                    return true;
-                 return expand_vselect (gen_lowpart (V4DImode, d->target),
-                                        gen_lowpart (V4DImode, d->op0),
-                                        perm, 4, false);
+                 target = gen_reg_rtx (V4DImode);
+                 if (expand_vselect (target, gen_lowpart (V4DImode, d->op0),
+                                     perm, 4, false))
+                   {
+                     emit_move_insn (d->target,
+                                     gen_lowpart (d->vmode, target));
+                     return true;
+                   }
+                 return false;
                }
  
              /* Next see if vpermd can be used.  */
                                gen_rtvec_v (GET_MODE_NUNITS (vmode), rperm));
    vperm = force_reg (vmode, vperm);
  
-   target = gen_lowpart (vmode, d->target);
+   target = d->target;
+   if (d->vmode != vmode)
+     target = gen_reg_rtx (vmode);
    op0 = gen_lowpart (vmode, d->op0);
    if (d->one_operand_p)
      {
        op1 = gen_lowpart (vmode, d->op1);
        emit_insn (gen_xop_pperm (target, op0, op1, vperm));
      }
+   if (target != d->target)
+     emit_move_insn (d->target, gen_lowpart (d->vmode, target));
  
    return true;
  }
@@@ -39704,7 -40043,8 +40043,8 @@@ expand_vec_perm_palignr (struct expand_
    unsigned i, nelt = d->nelt;
    unsigned min, max;
    bool in_order, ok;
-   rtx shift;
+   rtx shift, target;
+   struct expand_vec_perm_d dcopy;
  
    /* Even with AVX, palignr only operates on 128-bit vectors.  */
    if (!TARGET_SSSE3 || GET_MODE_SIZE (d->vmode) != 16)
    if (d->testing_p)
      return true;
  
+   dcopy = *d;
    shift = GEN_INT (min * GET_MODE_BITSIZE (GET_MODE_INNER (d->vmode)));
-   emit_insn (gen_ssse3_palignrti (gen_lowpart (TImode, d->target),
-                                 gen_lowpart (TImode, d->op1),
+   target = gen_reg_rtx (TImode);
+   emit_insn (gen_ssse3_palignrti (target, gen_lowpart (TImode, d->op1),
                                  gen_lowpart (TImode, d->op0), shift));
  
-   d->op0 = d->op1 = d->target;
-   d->one_operand_p = true;
+   dcopy.op0 = dcopy.op1 = gen_lowpart (d->vmode, target);
+   dcopy.one_operand_p = true;
  
    in_order = true;
    for (i = 0; i < nelt; ++i)
      {
-       unsigned e = d->perm[i] - min;
+       unsigned e = dcopy.perm[i] - min;
        if (e != i)
        in_order = false;
-       d->perm[i] = e;
+       dcopy.perm[i] = e;
      }
  
    /* Test for the degenerate case where the alignment by itself
       produces the desired permutation.  */
    if (in_order)
-     return true;
+     {
+       emit_move_insn (d->target, dcopy.op0);
+       return true;
+     }
  
-   ok = expand_vec_perm_1 (d);
+   ok = expand_vec_perm_1 (&dcopy);
    gcc_assert (ok);
  
    return ok;
@@@ -40003,10 -40347,10 +40347,10 @@@ expand_vec_perm_interleave2 (struct exp
        else
        dfinal.perm[i] = e;
      }
-   dfinal.op0 = gen_reg_rtx (dfinal.vmode);
+   dremap.target = gen_reg_rtx (dremap.vmode);
+   dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
    dfinal.op1 = dfinal.op0;
    dfinal.one_operand_p = true;
-   dremap.target = dfinal.op0;
  
    /* Test if the final remap can be done with a single insn.  For V4SFmode or
       V4SImode this *will* succeed.  For V8HImode or V16QImode it may not.  */
  
    if (dremap.vmode != dfinal.vmode)
      {
-       dremap.target = gen_lowpart (dremap.vmode, dremap.target);
        dremap.op0 = gen_lowpart (dremap.vmode, dremap.op0);
        dremap.op1 = gen_lowpart (dremap.vmode, dremap.op1);
      }
@@@ -40474,8 -40817,12 +40817,12 @@@ expand_vec_perm_pshufb2 (struct expand_
    op = gen_lowpart (V16QImode, d->op1);
    emit_insn (gen_ssse3_pshufbv16qi3 (h, op, vperm));
  
-   op = gen_lowpart (V16QImode, d->target);
+   op = d->target;
+   if (d->vmode != V16QImode)
+     op = gen_reg_rtx (V16QImode);
    emit_insn (gen_iorv16qi3 (op, l, h));
+   if (op != d->target)
+     emit_move_insn (d->target, gen_lowpart (d->vmode, op));
  
    return true;
  }
@@@ -40541,8 -40888,12 +40888,12 @@@ expand_vec_perm_vpshufb2_vpermq (struc
    op = gen_lowpart (V32QImode, d->op0);
    emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
  
-   op = gen_lowpart (V32QImode, d->target);
+   op = d->target;
+   if (d->vmode != V32QImode)
+     op = gen_reg_rtx (V32QImode);
    emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp)));
+   if (op != d->target)
+     emit_move_insn (d->target, gen_lowpart (d->vmode, op));
  
    return true;
  }
@@@ -40618,10 -40969,11 +40969,11 @@@ expand_vec_perm_vpshufb2_vpermq_even_od
    emit_insn (gen_iorv32qi3 (ior, l, h));
  
    /* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation.  */
-   op = gen_lowpart (V4DImode, d->target);
+   op = gen_reg_rtx (V4DImode);
    ior = gen_lowpart (V4DImode, ior);
    emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx,
                                  const1_rtx, GEN_INT (3)));
+   emit_move_insn (d->target, gen_lowpart (d->vmode, op));
  
    return true;
  }
  static bool
  expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
  {
-   rtx t1, t2, t3;
+   rtx t1, t2, t3, t4, t5;
  
    switch (d->vmode)
      {
        {
          struct expand_vec_perm_d d_copy = *d;
          d_copy.vmode = V4DFmode;
-         d_copy.target = gen_lowpart (V4DFmode, d->target);
+         d_copy.target = gen_reg_rtx (V4DFmode);
          d_copy.op0 = gen_lowpart (V4DFmode, d->op0);
          d_copy.op1 = gen_lowpart (V4DFmode, d->op1);
-         return expand_vec_perm_even_odd_1 (&d_copy, odd);
+         if (expand_vec_perm_even_odd_1 (&d_copy, odd))
+           {
+             if (!d->testing_p)
+               emit_move_insn (d->target,
+                               gen_lowpart (V4DImode, d_copy.target));
+             return true;
+           }
+         return false;
        }
  
        t1 = gen_reg_rtx (V4DImode);
        {
          struct expand_vec_perm_d d_copy = *d;
          d_copy.vmode = V8SFmode;
-         d_copy.target = gen_lowpart (V8SFmode, d->target);
+         d_copy.target = gen_reg_rtx (V8SFmode);
          d_copy.op0 = gen_lowpart (V8SFmode, d->op0);
          d_copy.op1 = gen_lowpart (V8SFmode, d->op1);
-         return expand_vec_perm_even_odd_1 (&d_copy, odd);
+         if (expand_vec_perm_even_odd_1 (&d_copy, odd))
+           {
+             if (!d->testing_p)
+               emit_move_insn (d->target,
+                               gen_lowpart (V8SImode, d_copy.target));
+             return true;
+           }
+         return false;
        }
  
        t1 = gen_reg_rtx (V8SImode);
        t2 = gen_reg_rtx (V8SImode);
+       t3 = gen_reg_rtx (V4DImode);
+       t4 = gen_reg_rtx (V4DImode);
+       t5 = gen_reg_rtx (V4DImode);
  
        /* Shuffle the lanes around into
         { 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }.  */
-       emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t1),
-                                   gen_lowpart (V4DImode, d->op0),
+       emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, d->op0),
                                    gen_lowpart (V4DImode, d->op1),
                                    GEN_INT (0x20)));
-       emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t2),
-                                   gen_lowpart (V4DImode, d->op0),
+       emit_insn (gen_avx2_permv2ti (t4, gen_lowpart (V4DImode, d->op0),
                                    gen_lowpart (V4DImode, d->op1),
                                    GEN_INT (0x31)));
  
        /* Swap the 2nd and 3rd position in each lane into
         { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }.  */
-       emit_insn (gen_avx2_pshufdv3 (t1, t1,
+       emit_insn (gen_avx2_pshufdv3 (t1, gen_lowpart (V8SImode, t3),
                                    GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
-       emit_insn (gen_avx2_pshufdv3 (t2, t2,
+       emit_insn (gen_avx2_pshufdv3 (t2, gen_lowpart (V8SImode, t4),
                                    GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
  
        /* Now an vpunpck[lh]qdq will produce
         { 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }.  */
        if (odd)
-       t3 = gen_avx2_interleave_highv4di (gen_lowpart (V4DImode, d->target),
-                                          gen_lowpart (V4DImode, t1),
+       t3 = gen_avx2_interleave_highv4di (t5, gen_lowpart (V4DImode, t1),
                                           gen_lowpart (V4DImode, t2));
        else
-       t3 = gen_avx2_interleave_lowv4di (gen_lowpart (V4DImode, d->target),
-                                         gen_lowpart (V4DImode, t1),
+       t3 = gen_avx2_interleave_lowv4di (t5, gen_lowpart (V4DImode, t1),
                                          gen_lowpart (V4DImode, t2));
        emit_insn (t3);
+       emit_move_insn (d->target, gen_lowpart (V8SImode, t5));
        break;
  
      default:
@@@ -40845,7 -41211,7 +41211,7 @@@ expand_vec_perm_broadcast_1 (struct exp
    unsigned elt = d->perm[0], nelt2 = d->nelt / 2;
    enum machine_mode vmode = d->vmode;
    unsigned char perm2[4];
-   rtx op0 = d->op0;
+   rtx op0 = d->op0, dest;
    bool ok;
  
    switch (vmode)
        while (vmode != V4SImode);
  
        memset (perm2, elt, 4);
-       ok = expand_vselect (gen_lowpart (V4SImode, d->target), op0, perm2, 4,
-                          d->testing_p);
+       dest = gen_reg_rtx (V4SImode);
+       ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
        gcc_assert (ok);
+       if (!d->testing_p)
+       emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
        return true;
  
      case V32QImode:
@@@ -41035,8 -41403,12 +41403,12 @@@ expand_vec_perm_vpshufb4_vpermq2 (struc
      }
  
    gcc_assert (l[0] && l[1]);
-   op = gen_lowpart (V32QImode, d->target);
+   op = d->target;
+   if (d->vmode != V32QImode)
+     op = gen_reg_rtx (V32QImode);
    emit_insn (gen_iorv32qi3 (op, l[0], l[1]));
+   if (op != d->target)
+     emit_move_insn (d->target, gen_lowpart (d->vmode, op));
    return true;
  }
  
@@@ -41604,7 -41976,9 +41976,9 @@@ ix86_expand_mul_widen_hilo (rtx dest, r
                         op1, op2, NULL_RTX, uns_p, OPTAB_DIRECT);
        gcc_assert (t1 && t2);
  
-       ix86_expand_vec_interleave (gen_lowpart (mode, dest), t1, t2, high_p);
+       t3 = gen_reg_rtx (mode);
+       ix86_expand_vec_interleave (t3, t1, t2, high_p);
+       emit_move_insn (dest, gen_lowpart (wmode, t3));
        break;
  
      case V16QImode:
  void
  ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2)
  {
-   rtx res_1, res_2;
+   rtx res_1, res_2, res_3, res_4;
  
    res_1 = gen_reg_rtx (V4SImode);
    res_2 = gen_reg_rtx (V4SImode);
-   ix86_expand_mul_widen_evenodd (gen_lowpart (V2DImode, res_1),
-                                op1, op2, true, false);
-   ix86_expand_mul_widen_evenodd (gen_lowpart (V2DImode, res_2),
-                                op1, op2, true, true);
+   res_3 = gen_reg_rtx (V2DImode);
+   res_4 = gen_reg_rtx (V2DImode);
+   ix86_expand_mul_widen_evenodd (res_3, op1, op2, true, false);
+   ix86_expand_mul_widen_evenodd (res_4, op1, op2, true, true);
  
    /* Move the results in element 2 down to element 1; we don't care
       what goes in elements 2 and 3.  Then we can merge the parts
       In both cases the cost of the reformatting stall was too high
       and the overall sequence slower.  */
  
-   emit_insn (gen_sse2_pshufd_1 (res_1, res_1, const0_rtx, const2_rtx,
+   emit_insn (gen_sse2_pshufd_1 (res_1, gen_lowpart (V4SImode, res_3),
+                               const0_rtx, const2_rtx,
                                const0_rtx, const0_rtx));
-   emit_insn (gen_sse2_pshufd_1 (res_2, res_2, const0_rtx, const2_rtx,
+   emit_insn (gen_sse2_pshufd_1 (res_2, gen_lowpart (V4SImode, res_4),
+                               const0_rtx, const2_rtx,
                                const0_rtx, const0_rtx));
    res_1 = emit_insn (gen_vec_interleave_lowv4si (op0, res_1, res_2));
  
@@@ -41737,6 -42113,68 +42113,68 @@@ ix86_expand_sse2_mulvxdi3 (rtx op0, rt
                       gen_rtx_MULT (mode, op1, op2));
  }
  
+ /* Return 1 if control tansfer instruction INSN
+    should be encoded with bnd prefix.
+    If insn is NULL then return 1 when control
+    transfer instructions should be prefixed with
+    bnd by default for current function.  */
+ bool
+ ix86_bnd_prefixed_insn_p (rtx insn ATTRIBUTE_UNUSED)
+ {
+   return false;
+ }
+ /* Calculate integer abs() using only SSE2 instructions.  */
+ void
+ ix86_expand_sse2_abs (rtx target, rtx input)
+ {
+   enum machine_mode mode = GET_MODE (target);
+   rtx tmp0, tmp1, x;
+   switch (mode)
+     {
+       /* For 32-bit signed integer X, the best way to calculate the absolute
+        value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)).  */
+       case V4SImode:
+       tmp0 = expand_simple_binop (mode, ASHIFTRT, input,
+                                   GEN_INT (GET_MODE_BITSIZE
+                                            (GET_MODE_INNER (mode)) - 1),
+                                   NULL, 0, OPTAB_DIRECT);
+       tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
+                                   NULL, 0, OPTAB_DIRECT);
+       x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
+                                target, 0, OPTAB_DIRECT);
+       break;
+       /* For 16-bit signed integer X, the best way to calculate the absolute
+        value of X is max (X, -X), as SSE2 provides the PMAXSW insn.  */
+       case V8HImode:
+       tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
+       x = expand_simple_binop (mode, SMAX, tmp0, input,
+                                target, 0, OPTAB_DIRECT);
+       break;
+       /* For 8-bit signed integer X, the best way to calculate the absolute
+        value of X is min ((unsigned char) X, (unsigned char) (-X)),
+        as SSE2 provides the PMINUB insn.  */
+       case V16QImode:
+       tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
+       x = expand_simple_binop (V16QImode, UMIN, tmp0, input,
+                                target, 0, OPTAB_DIRECT);
+       break;
+       default:
+       gcc_unreachable ();
+     }
+   if (x != target)
+     emit_move_insn (target, x);
+ }
  /* Expand an insert into a vector register through pinsr insn.
     Return true if successful.  */
  
@@@ -41805,12 -42243,17 +42243,17 @@@ ix86_expand_pinsr (rtx *operands
            return false;
          }
  
-       dst = gen_lowpart (dstmode, dst);
+       rtx d = dst;
+       if (GET_MODE (dst) != dstmode)
+         d = gen_reg_rtx (dstmode);
        src = gen_lowpart (srcmode, src);
  
        pos /= size;
  
-       emit_insn (pinsr (dst, dst, src, GEN_INT (1 << pos)));
+       emit_insn (pinsr (d, gen_lowpart (dstmode, dst), src,
+                         GEN_INT (1 << pos)));
+       if (d != dst)
+         emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
        return true;
        }
  
diff --combined gcc/config/mips/mips.c
index 5040b40def52023ec2ead1dca238363a7d6d20b5,60e5e788f902fef2d9aa1e3e762d1f34441a3963..510204203e1b1863797d986993e552cc8df810ab
@@@ -3796,6 -3796,18 +3796,18 @@@ mips_rtx_costs (rtx x, int code, int ou
              return true;
            }
        }
+       /* (AND (NOT op0) (NOT op1) is a nor operation that can be done in
+        a single instruction.  */
+       if (!TARGET_MIPS16
+         && GET_CODE (XEXP (x, 0)) == NOT
+         && GET_CODE (XEXP (x, 1)) == NOT)
+       {
+         cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1;
+           *total = (COSTS_N_INSNS (cost)
+                   + set_src_cost (XEXP (XEXP (x, 0), 0), speed)
+                   + set_src_cost (XEXP (XEXP (x, 1), 0), speed));
+         return true;
+       }
            
        /* Fall through.  */
  
@@@ -5136,7 -5148,7 +5148,7 @@@ mips_function_arg (cumulative_args_t cu
        && type != 0
        && TREE_CODE (type) == RECORD_TYPE
        && TYPE_SIZE_UNIT (type)
 -      && host_integerp (TYPE_SIZE_UNIT (type), 1))
 +      && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
      {
        tree field;
  
        if (TREE_CODE (field) == FIELD_DECL
            && SCALAR_FLOAT_TYPE_P (TREE_TYPE (field))
            && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
 -          && host_integerp (bit_position (field), 0)
 +          && tree_fits_shwi_p (bit_position (field))
            && int_bit_position (field) % BITS_PER_WORD == 0)
          break;
  
@@@ -14905,7 -14917,7 +14917,7 @@@ r10k_safe_address_p (rtx x, rtx insn
     a link-time-constant address.  */
  
  static bool
 -r10k_safe_mem_expr_p (tree expr, HOST_WIDE_INT offset)
 +r10k_safe_mem_expr_p (tree expr, unsigned HOST_WIDE_INT offset)
  {
    HOST_WIDE_INT bitoffset, bitsize;
    tree inner, var_offset;
      return false;
  
    offset += bitoffset / BITS_PER_UNIT;
 -  return offset >= 0 && offset < tree_low_cst (DECL_SIZE_UNIT (inner), 1);
 +  return offset < tree_to_uhwi (DECL_SIZE_UNIT (inner));
  }
  
  /* A for_each_rtx callback for which DATA points to the instruction
index c3a91891f1130946537c56d7c971fb9b7d7ae9f3,31871b46bd8ae95e85cb0cdf9a44ecb2451e582f..1deb3e5c3e7f4b2532c09377e552be57f0d6c785
@@@ -55,6 -55,7 +55,7 @@@
  #include "intl.h"
  #include "params.h"
  #include "tm-constrs.h"
+ #include "ira.h"
  #include "opts.h"
  #include "tree-vectorizer.h"
  #include "dumpfile.h"
@@@ -1554,6 -1555,9 +1555,9 @@@ static const struct attribute_spec rs60
  #undef TARGET_MODE_DEPENDENT_ADDRESS_P
  #define TARGET_MODE_DEPENDENT_ADDRESS_P rs6000_mode_dependent_address_p
  
+ #undef TARGET_LRA_P
+ #define TARGET_LRA_P rs6000_lra_p
  #undef TARGET_CAN_ELIMINATE
  #define TARGET_CAN_ELIMINATE rs6000_can_eliminate
  
@@@ -4024,7 -4028,7 +4028,7 @@@ rs6000_builtin_support_vector_misalignm
             it's word aligned.  */
          if (rs6000_vector_alignment_reachable (type, is_packed))
              {
 -              int element_size = TREE_INT_CST_LOW (TYPE_SIZE (type));
 +              int element_size = tree_to_hwi (TYPE_SIZE (type));
  
                if (element_size == 64 || element_size == 32)
                 return true;
@@@ -4844,15 -4848,6 +4848,15 @@@ num_insns_constant (rtx op, enum machin
        else
        return num_insns_constant_wide (INTVAL (op));
  
 +    case CONST_WIDE_INT:
 +      {
 +      int i;
 +      int ins = CONST_WIDE_INT_NUNITS (op) - 1;
 +      for (i = 0; i < CONST_WIDE_INT_NUNITS (op); i++)
 +        ins += num_insns_constant_wide (CONST_WIDE_INT_ELT (op, i));
 +      return ins;
 +      }
 +
        case CONST_DOUBLE:
        if (mode == SFmode || mode == SDmode)
          {
@@@ -5027,8 -5022,8 +5031,8 @@@ easy_altivec_constant (rtx op, enum mac
  
    if (mode == V2DImode)
      {
 -      /* In case the compiler is built 32-bit, CONST_DOUBLE constants are not
 -       easy.  */
 +      /* In case the compiler is built 32-bit, CONST_WIDE_INT
 +       constants are not easy.  */
        if (GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT
          || GET_CODE (CONST_VECTOR_ELT (op, 1)) != CONST_INT)
        return false;
@@@ -5189,7 -5184,9 +5193,7 @@@ paired_expand_vector_init (rtx target, 
    for (i = 0; i < n_elts; ++i)
      {
        x = XVECEXP (vals, 0, i);
 -      if (!(CONST_INT_P (x)
 -          || GET_CODE (x) == CONST_DOUBLE
 -          || GET_CODE (x) == CONST_FIXED))
 +      if (!CONSTANT_P (x))
        ++n_var;
      }
    if (n_var == 0)
@@@ -5341,7 -5338,9 +5345,7 @@@ rs6000_expand_vector_init (rtx target, 
    for (i = 0; i < n_elts; ++i)
      {
        x = XVECEXP (vals, 0, i);
 -      if (!(CONST_INT_P (x)
 -          || GET_CODE (x) == CONST_DOUBLE
 -          || GET_CODE (x) == CONST_FIXED))
 +      if (!CONSTANT_P (x))
        ++n_var, one_var = i;
        else if (x != CONST0_RTX (inner_mode))
        all_const_zero = false;
@@@ -5530,10 -5529,27 +5534,27 @@@ rs6000_expand_vector_set (rtx target, r
      XVECEXP (mask, 0, elt*width + i)
        = GEN_INT (i + 0x10);
    x = gen_rtx_CONST_VECTOR (V16QImode, XVEC (mask, 0));
-   x = gen_rtx_UNSPEC (mode,
-                     gen_rtvec (3, target, reg,
-                                force_reg (V16QImode, x)),
-                     UNSPEC_VPERM);
+   if (BYTES_BIG_ENDIAN)
+     x = gen_rtx_UNSPEC (mode,
+                       gen_rtvec (3, target, reg,
+                                  force_reg (V16QImode, x)),
+                       UNSPEC_VPERM);
+   else 
+     {
+       /* Invert selector.  */
+       rtx splat = gen_rtx_VEC_DUPLICATE (V16QImode,
+                                        gen_rtx_CONST_INT (QImode, -1));
+       rtx tmp = gen_reg_rtx (V16QImode);
+       emit_move_insn (tmp, splat);
+       x = gen_rtx_MINUS (V16QImode, tmp, force_reg (V16QImode, x));
+       emit_move_insn (tmp, x);
+       /* Permute with operands reversed and adjusted selector.  */
+       x = gen_rtx_UNSPEC (mode, gen_rtvec (3, reg, target, tmp),
+                         UNSPEC_VPERM);
+     }
    emit_insn (gen_rtx_SET (VOIDmode, target, x));
  }
  
@@@ -6097,10 -6113,10 +6118,10 @@@ offsettable_ok_by_alignment (rtx op, HO
          if (!DECL_SIZE_UNIT (decl))
            return false;
  
 -        if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
 +        if (!tree_fits_uhwi_p (DECL_SIZE_UNIT (decl)))
            return false;
 -
 -        dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
 +        
 +        dsize = tree_to_uhwi (DECL_SIZE_UNIT (decl));
          if (dsize > 32768)
            return false;
  
          if (TREE_CODE (decl) == STRING_CST)
            dsize = TREE_STRING_LENGTH (decl);
          else if (TYPE_SIZE_UNIT (type)
 -                 && host_integerp (TYPE_SIZE_UNIT (type), 1))
 -          dsize = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
 +                 && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
 +          dsize = tree_to_uhwi (TYPE_SIZE_UNIT (type));
          else
            return false;
          if (dsize > 32768)
@@@ -6231,7 -6247,7 +6252,7 @@@ rs6000_legitimate_offset_address_p (enu
      return false;
    if (!reg_offset_addressing_ok_p (mode))
      return virtual_stack_registers_memory_p (x);
-   if (legitimate_constant_pool_address_p (x, mode, strict))
+   if (legitimate_constant_pool_address_p (x, mode, strict || lra_in_progress))
      return true;
    if (GET_CODE (XEXP (x, 1)) != CONST_INT)
      return false;
@@@ -6371,19 -6387,31 +6392,31 @@@ legitimate_lo_sum_address_p (enum machi
  
    if (TARGET_ELF || TARGET_MACHO)
      {
+       bool large_toc_ok;
        if (DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_DARWIN && flag_pic)
        return false;
-       if (TARGET_TOC)
+       /* LRA don't use LEGITIMIZE_RELOAD_ADDRESS as it usually calls
+        push_reload from reload pass code.  LEGITIMIZE_RELOAD_ADDRESS
+        recognizes some LO_SUM addresses as valid although this
+        function says opposite.  In most cases, LRA through different
+        transformations can generate correct code for address reloads.
+        It can not manage only some LO_SUM cases.  So we need to add
+        code analogous to one in rs6000_legitimize_reload_address for
+        LOW_SUM here saying that some addresses are still valid.  */
+       large_toc_ok = (lra_in_progress && TARGET_CMODEL != CMODEL_SMALL
+                     && small_toc_ref (x, VOIDmode));
+       if (TARGET_TOC && ! large_toc_ok)
        return false;
        if (GET_MODE_NUNITS (mode) != 1)
        return false;
-       if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
+       if (! lra_in_progress && GET_MODE_SIZE (mode) > UNITS_PER_WORD
          && !(/* ??? Assume floating point reg based on mode?  */
               TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
               && (mode == DFmode || mode == DDmode)))
        return false;
  
-       return CONSTANT_P (x);
+       return CONSTANT_P (x) || large_toc_ok;
      }
  
    return false;
@@@ -6537,7 -6565,6 +6570,7 @@@ rs6000_legitimize_address (rtx x, rtx o
           && TARGET_NO_TOC
           && ! flag_pic
           && GET_CODE (x) != CONST_INT
 +         && GET_CODE (x) != CONST_WIDE_INT
           && GET_CODE (x) != CONST_DOUBLE
           && CONSTANT_P (x)
           && GET_MODE_NUNITS (mode) == 1
@@@ -7374,7 -7401,8 +7407,8 @@@ rs6000_legitimate_address_p (enum machi
    if (reg_offset_p && legitimate_small_data_p (mode, x))
      return 1;
    if (reg_offset_p
-       && legitimate_constant_pool_address_p (x, mode, reg_ok_strict))
+       && legitimate_constant_pool_address_p (x, mode,
+                                            reg_ok_strict || lra_in_progress))
      return 1;
    /* For TImode, if we have load/store quad and TImode in VSX registers, only
       allow register indirect addresses.  This will allow the values to go in
@@@ -7660,6 -7688,7 +7694,7 @@@ rs6000_conditional_register_usage (void
          fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
      }
  }
  \f
  /* Try to output insns to set TARGET equal to the constant C if it can
     be done in less than N insns.  Do all computations in MODE.
@@@ -7969,12 -7998,21 +8004,12 @@@ rs6000_emit_move (rtx dest, rtx source
      }
  
    /* Sanity checks.  Check that we get CONST_DOUBLE only when we should.  */
 -  if (GET_CODE (operands[1]) == CONST_DOUBLE
 -      && ! FLOAT_MODE_P (mode)
 +  if (CONST_WIDE_INT_P (operands[1])
        && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
      {
 -      /* FIXME.  This should never happen.  */
 -      /* Since it seems that it does, do the safe thing and convert
 -       to a CONST_INT.  */
 -      operands[1] = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), mode);
 +      /* This should be fixed with the introduction of CONST_WIDE_INT.  */
 +      gcc_unreachable ();
      }
 -  gcc_assert (GET_CODE (operands[1]) != CONST_DOUBLE
 -            || FLOAT_MODE_P (mode)
 -            || ((CONST_DOUBLE_HIGH (operands[1]) != 0
 -                 || CONST_DOUBLE_LOW (operands[1]) < 0)
 -                && (CONST_DOUBLE_HIGH (operands[1]) != -1
 -                    || CONST_DOUBLE_LOW (operands[1]) >= 0)));
  
    /* Check if GCC is setting up a block move that will end up using FP
       registers as temporaries.  We must make sure this is acceptable.  */
      cfun->machine->sdmode_stack_slot =
        eliminate_regs (cfun->machine->sdmode_stack_slot, VOIDmode, NULL_RTX);
  
+   if (lra_in_progress
+       && mode == SDmode
+       && REG_P (operands[0]) && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER
+       && reg_preferred_class (REGNO (operands[0])) == NO_REGS
+       && (REG_P (operands[1])
+         || (GET_CODE (operands[1]) == SUBREG
+             && REG_P (SUBREG_REG (operands[1])))))
+     {
+       int regno = REGNO (GET_CODE (operands[1]) == SUBREG
+                        ? SUBREG_REG (operands[1]) : operands[1]);
+       enum reg_class cl;
+       if (regno >= FIRST_PSEUDO_REGISTER)
+       {
+         cl = reg_preferred_class (regno);
+         gcc_assert (cl != NO_REGS);
+         regno = ira_class_hard_regs[cl][0];
+       }
+       if (FP_REGNO_P (regno))
+       {
+         if (GET_MODE (operands[0]) != DDmode)
+           operands[0] = gen_rtx_SUBREG (DDmode, operands[0], 0);
+         emit_insn (gen_movsd_store (operands[0], operands[1]));
+       }
+       else if (INT_REGNO_P (regno))
+       emit_insn (gen_movsd_hardfloat (operands[0], operands[1]));
+       else
+       gcc_unreachable();
+       return;
+     }
+   if (lra_in_progress
+       && mode == SDmode
+       && (REG_P (operands[0])
+         || (GET_CODE (operands[0]) == SUBREG
+             && REG_P (SUBREG_REG (operands[0]))))
+       && REG_P (operands[1]) && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER
+       && reg_preferred_class (REGNO (operands[1])) == NO_REGS)
+     {
+       int regno = REGNO (GET_CODE (operands[0]) == SUBREG
+                        ? SUBREG_REG (operands[0]) : operands[0]);
+       enum reg_class cl;
+       if (regno >= FIRST_PSEUDO_REGISTER)
+       {
+         cl = reg_preferred_class (regno);
+         gcc_assert (cl != NO_REGS);
+         regno = ira_class_hard_regs[cl][0];
+       }
+       if (FP_REGNO_P (regno))
+       {
+         if (GET_MODE (operands[1]) != DDmode)
+           operands[1] = gen_rtx_SUBREG (DDmode, operands[1], 0);
+         emit_insn (gen_movsd_load (operands[0], operands[1]));
+       }
+       else if (INT_REGNO_P (regno))
+       emit_insn (gen_movsd_hardfloat (operands[0], operands[1]));
+       else
+       gcc_unreachable();
+       return;
+     }
    if (reload_in_progress
        && mode == SDmode
        && cfun->machine->sdmode_stack_slot != NULL_RTX
@@@ -8787,7 -8887,7 +8884,7 @@@ rs6000_darwin64_record_arg_advance_recu
        mode = TYPE_MODE (ftype);
  
        if (DECL_SIZE (f) != 0
 -          && host_integerp (bit_position (f), 1))
 +          && tree_fits_uhwi_p (bit_position (f)))
          bitpos += int_bit_position (f);
  
        /* ??? FIXME: else assume zero offset.  */
@@@ -9264,7 -9364,7 +9361,7 @@@ rs6000_darwin64_record_arg_recurse (CUM
        mode = TYPE_MODE (ftype);
  
        if (DECL_SIZE (f) != 0
 -          && host_integerp (bit_position (f), 1))
 +          && tree_fits_uhwi_p (bit_position (f)))
          bitpos += int_bit_position (f);
  
        /* ??? FIXME: else assume zero offset.  */
@@@ -11003,7 -11103,7 +11100,7 @@@ rs6000_expand_binop_builtin (enum insn_
        /* Only allow 5-bit unsigned literals.  */
        STRIP_NOPS (arg1);
        if (TREE_CODE (arg1) != INTEGER_CST
 -        || TREE_INT_CST_LOW (arg1) & ~0x1f)
 +        || tree_to_hwi (arg1) & ~0x1f)
        {
          error ("argument 2 must be a 5-bit unsigned literal");
          return const0_rtx;
@@@ -11048,7 -11148,7 +11145,7 @@@ altivec_expand_predicate_builtin (enum 
        return const0_rtx;
      }
    else
 -    cr6_form_int = TREE_INT_CST_LOW (cr6_form);
 +    cr6_form_int = tree_to_hwi (cr6_form);
  
    gcc_assert (mode0 == mode1);
  
@@@ -11539,7 -11639,7 +11636,7 @@@ rs6000_expand_ternop_builtin (enum insn
        /* Only allow 4-bit unsigned literals.  */
        STRIP_NOPS (arg2);
        if (TREE_CODE (arg2) != INTEGER_CST
 -        || TREE_INT_CST_LOW (arg2) & ~0xf)
 +        || tree_to_hwi (arg2) & ~0xf)
        {
          error ("argument 3 must be a 4-bit unsigned literal");
          return const0_rtx;
        /* Only allow 2-bit unsigned literals.  */
        STRIP_NOPS (arg2);
        if (TREE_CODE (arg2) != INTEGER_CST
 -        || TREE_INT_CST_LOW (arg2) & ~0x3)
 +        || tree_to_hwi (arg2) & ~0x3)
        {
          error ("argument 3 must be a 2-bit unsigned literal");
          return const0_rtx;
        /* Only allow 1-bit unsigned literals.  */
        STRIP_NOPS (arg2);
        if (TREE_CODE (arg2) != INTEGER_CST
 -        || TREE_INT_CST_LOW (arg2) & ~0x1)
 +        || tree_to_hwi (arg2) & ~0x1)
        {
          error ("argument 3 must be a 1-bit unsigned literal");
          return const0_rtx;
         range and prepare arguments.  */
        STRIP_NOPS (arg1);
        if (TREE_CODE (arg1) != INTEGER_CST
 -        || !IN_RANGE (TREE_INT_CST_LOW (arg1), 0, 1))
 +        || !IN_RANGE (TREE_INT_CST_ELT (arg1, 0), 0, 1))
        {
          error ("argument 2 must be 0 or 1");
          return const0_rtx;
  
        STRIP_NOPS (arg2);
        if (TREE_CODE (arg2) != INTEGER_CST
 -        || !IN_RANGE (TREE_INT_CST_LOW (arg2), 0, 15))
 +        || !IN_RANGE (TREE_INT_CST_ELT (arg2, 0), 0, 15))
        {
          error ("argument 3 must be in the range 0..15");
          return const0_rtx;
@@@ -11773,7 -11873,7 +11870,7 @@@ altivec_expand_dst_builtin (tree exp, r
        *expandedp = true;
        STRIP_NOPS (arg2);
        if (TREE_CODE (arg2) != INTEGER_CST
 -          || TREE_INT_CST_LOW (arg2) & ~0x3)
 +          || tree_to_hwi (arg2) & ~0x3)
          {
            error ("argument to %qs must be a 2-bit unsigned literal", d->name);
            return const0_rtx;
@@@ -11827,8 -11927,8 +11924,8 @@@ get_element_number (tree vec_type, tre
  {
    unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
  
 -  if (!host_integerp (arg, 1)
 -      || (elt = tree_low_cst (arg, 1), elt > max))
 +  if (!tree_fits_uhwi_p (arg)
 +      || (elt = tree_to_uhwi (arg), elt > max))
      {
        error ("selector must be an integer constant in the range 0..%wi", max);
        return 0;
@@@ -12020,7 -12120,7 +12117,7 @@@ altivec_expand_builtin (tree exp, rtx t
        return const0_rtx;
  
        if (TREE_CODE (arg0) != INTEGER_CST
 -        || TREE_INT_CST_LOW (arg0) & ~0x3)
 +        || tree_to_hwi (arg0) & ~0x3)
        {
          error ("argument to dss must be a 2-bit unsigned literal");
          return const0_rtx;
@@@ -12229,7 -12329,7 +12326,7 @@@ spe_expand_builtin (tree exp, rtx targe
      case SPE_BUILTIN_EVSTWWO:
        arg1 = CALL_EXPR_ARG (exp, 2);
        if (TREE_CODE (arg1) != INTEGER_CST
 -        || TREE_INT_CST_LOW (arg1) & ~0x1f)
 +        || tree_to_hwi (arg1) & ~0x1f)
        {
          error ("argument 2 must be a 5-bit unsigned literal");
          return const0_rtx;
@@@ -12355,7 -12455,7 +12452,7 @@@ paired_expand_predicate_builtin (enum i
        return const0_rtx;
      }
    else
 -    form_int = TREE_INT_CST_LOW (form);
 +    form_int = tree_to_hwi (form);
  
    gcc_assert (mode0 == mode1);
  
@@@ -12427,7 -12527,7 +12524,7 @@@ spe_expand_predicate_builtin (enum insn
        return const0_rtx;
      }
    else
 -    form_int = TREE_INT_CST_LOW (form);
 +    form_int = tree_to_hwi (form);
  
    gcc_assert (mode0 == mode1);
  
@@@ -14902,6 -15002,17 +14999,17 @@@ rs6000_secondary_memory_needed_rtx (enu
    return ret;
  }
  
+ /* Return the mode to be used for memory when a secondary memory
+    location is needed.  For SDmode values we need to use DDmode, in
+    all other cases we can use the same mode.  */
+ enum machine_mode
+ rs6000_secondary_memory_needed_mode (enum machine_mode mode)
+ {
+   if (mode == SDmode)
+     return DDmode;
+   return mode;
+ }
  static tree
  rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
  {
@@@ -15795,6 -15906,10 +15903,10 @@@ rs6000_alloc_sdmode_stack_slot (void
    gimple_stmt_iterator gsi;
  
    gcc_assert (cfun->machine->sdmode_stack_slot == NULL_RTX);
+   /* We use a different approach for dealing with the secondary
+      memory in LRA.  */
+   if (ira_use_lra_p)
+     return;
  
    if (TARGET_NO_SDMODE_STACK)
      return;
@@@ -16016,7 -16131,7 +16128,7 @@@ rs6000_secondary_reload_class (enum reg
    /* Constants, memory, and FP registers can go into FP registers.  */
    if ((regno == -1 || FP_REGNO_P (regno))
        && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
-     return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
+     return (mode != SDmode || lra_in_progress) ? NO_REGS : GENERAL_REGS;
  
    /* Memory, and FP/altivec registers can go into fp/altivec registers under
       VSX.  However, for scalar variables, use the traditional floating point
@@@ -16290,7 -16405,6 +16402,7 @@@ rs6000_output_move_128bit (rtx operands
    /* Constants.  */
    else if (dest_regno >= 0
           && (GET_CODE (src) == CONST_INT
 +             || GET_CODE (src) == CONST_WIDE_INT
               || GET_CODE (src) == CONST_DOUBLE
               || GET_CODE (src) == CONST_VECTOR))
      {
@@@ -17304,7 -17418,8 +17416,7 @@@ rs6000_assemble_integer (rtx x, unsigne
        if (TARGET_RELOCATABLE
          && in_section != toc_section
          && !recurse
 -        && GET_CODE (x) != CONST_INT
 -        && GET_CODE (x) != CONST_DOUBLE
 +        && !CONST_SCALAR_INT_P (x)
          && CONSTANT_P (x))
        {
          char buf[256];
@@@ -23692,15 -23807,6 +23804,15 @@@ rs6000_hash_constant (rtx k
      case LABEL_REF:
        return result * 1231 + (unsigned) INSN_UID (XEXP (k, 0));
  
 +    case CONST_WIDE_INT:
 +      {
 +      int i;
 +      flen = CONST_WIDE_INT_NUNITS (k);
 +      for (i = 0; i < flen; i++)
 +        result = result * 613 + CONST_WIDE_INT_ELT (k, i);
 +      return result;
 +      }
 +
      case CONST_DOUBLE:
        if (mode != VOIDmode)
        return real_hash (CONST_DOUBLE_REAL_VALUE (k)) * result;
@@@ -23905,7 -24011,7 +24017,7 @@@ output_toc (FILE *file, rtx x, int labe
  
    /* If we're going to put a double constant in the TOC, make sure it's
       aligned properly when strict alignment is on.  */
 -  if (GET_CODE (x) == CONST_DOUBLE
 +  if ((CONST_DOUBLE_P (x) || CONST_WIDE_INT_P (x))
        && STRICT_ALIGNMENT
        && GET_MODE_BITSIZE (mode) >= 64
        && ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC)) {
@@@ -27907,7 -28013,6 +28019,7 @@@ rs6000_rtx_costs (rtx x, int code, int 
        /* FALLTHRU */
  
      case CONST_DOUBLE:
 +    case CONST_WIDE_INT:
      case CONST:
      case HIGH:
      case SYMBOL_REF:
@@@ -28547,7 -28652,7 +28659,7 @@@ rs6000_emit_swrsqrt (rtx dst, rtx src
    gcc_assert (code != CODE_FOR_nothing);
  
    /* Load up the constant 1.5 either as a scalar, or as a vector.  */
 -  real_from_integer (&dconst3_2, VOIDmode, 3, 0, 0);
 +  real_from_integer (&dconst3_2, VOIDmode, 3, SIGNED);
    SET_REAL_EXP (&dconst3_2, REAL_EXP (&dconst3_2) - 1);
  
    halfthree = rs6000_load_constant_and_splat (mode, dconst3_2);
@@@ -28845,17 -28950,23 +28957,23 @@@ altivec_expand_vec_perm_const (rtx oper
        {  1,  3,  5,  7,  9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 } },
      { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum,
        {  2,  3,  6,  7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 } },
-     { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghb,
+     { OPTION_MASK_ALTIVEC, 
+       BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb : CODE_FOR_altivec_vmrglb,
        {  0, 16,  1, 17,  2, 18,  3, 19,  4, 20,  5, 21,  6, 22,  7, 23 } },
-     { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghh,
+     { OPTION_MASK_ALTIVEC,
+       BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh : CODE_FOR_altivec_vmrglh,
        {  0,  1, 16, 17,  2,  3, 18, 19,  4,  5, 20, 21,  6,  7, 22, 23 } },
-     { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghw,
+     { OPTION_MASK_ALTIVEC,
+       BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw : CODE_FOR_altivec_vmrglw,
        {  0,  1,  2,  3, 16, 17, 18, 19,  4,  5,  6,  7, 20, 21, 22, 23 } },
-     { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglb,
+     { OPTION_MASK_ALTIVEC,
+       BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb : CODE_FOR_altivec_vmrghb,
        {  8, 24,  9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31 } },
-     { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglh,
+     { OPTION_MASK_ALTIVEC,
+       BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh : CODE_FOR_altivec_vmrghh,
        {  8,  9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 } },
-     { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglw,
+     { OPTION_MASK_ALTIVEC,
+       BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw : CODE_FOR_altivec_vmrghw,
        {  8,  9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31 } },
      { OPTION_MASK_P8_VECTOR, CODE_FOR_p8_vmrgew,
        {  0,  1,  2,  3, 16, 17, 18, 19,  8,  9, 10, 11, 24, 25, 26, 27 } },
          enum machine_mode omode = insn_data[icode].operand[0].mode;
          enum machine_mode imode = insn_data[icode].operand[1].mode;
  
+         /* For little-endian, don't use vpkuwum and vpkuhum if the
+            underlying vector type is not V4SI and V8HI, respectively.
+            For example, using vpkuwum with a V8HI picks up the even
+            halfwords (BE numbering) when the even halfwords (LE
+            numbering) are what we need.  */
+         if (!BYTES_BIG_ENDIAN
+             && icode == CODE_FOR_altivec_vpkuwum
+             && ((GET_CODE (op0) == REG
+                  && GET_MODE (op0) != V4SImode)
+                 || (GET_CODE (op0) == SUBREG
+                     && GET_MODE (XEXP (op0, 0)) != V4SImode)))
+           continue;
+         if (!BYTES_BIG_ENDIAN
+             && icode == CODE_FOR_altivec_vpkuhum
+             && ((GET_CODE (op0) == REG
+                  && GET_MODE (op0) != V8HImode)
+                 || (GET_CODE (op0) == SUBREG
+                     && GET_MODE (XEXP (op0, 0)) != V8HImode)))
+           continue;
            /* For little-endian, the two input operands must be swapped
               (or swapped back) to ensure proper right-to-left numbering
               from 0 to 2N-1.  */
@@@ -29345,6 -29476,13 +29483,13 @@@ rs6000_libcall_value (enum machine_mod
  }
  
  
+ /* Return true if we use LRA instead of reload pass.  */
+ static bool
+ rs6000_lra_p (void)
+ {
+   return rs6000_lra_flag;
+ }
  /* Given FROM and TO register numbers, say whether this elimination is allowed.
     Frame pointer elimination is automatically handled.
  
index 387d8c99ac12dc93da220bb62b151ccda4358e9e,f13951eb23555305b8a069cced1c08b1ffe003a3..9b167b7399e6a2c19b4755a307de5cc853bc9d5d
@@@ -1488,6 -1488,13 +1488,13 @@@ extern enum reg_class rs6000_constraint
  #define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
    rs6000_secondary_memory_needed_rtx (MODE)
  
+ /* Specify the mode to be used for memory when a secondary memory
+    location is needed.  For cpus that cannot load/store SDmode values
+    from the 64-bit FP registers without using a full 64-bit
+    load/store, we need a wider mode.  */
+ #define SECONDARY_MEMORY_NEEDED_MODE(MODE)            \
+   rs6000_secondary_memory_needed_mode (MODE)
  /* Return the maximum number of consecutive registers
     needed to represent mode MODE in a register of class CLASS.
  
@@@ -2645,4 -2652,3 +2652,4 @@@ enum rs6000_builtin_type_inde
  extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
  extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
  
 +#define TARGET_SUPPORTS_WIDE_INT 1
index 9961c1e9c2352520e28aa52020b907495fd1b5dd,9a0472d21a9eb5b89d0dd45360e4cb823077b073..11829189eb68f8585b34f8b3e95d502b73a8431b
                             (match_operand:SI 2 "gpc_reg_operand" "r,r"))
                    (const_int 0)))
     (clobber (match_scratch:SI 3 "=r,r"))]
-   ""
+   "TARGET_32BIT"
    "@
     mullw. %3,%1,%2
     #"
                             (match_operand:SI 2 "gpc_reg_operand" ""))
                    (const_int 0)))
     (clobber (match_scratch:SI 3 ""))]
-   "reload_completed"
+   "TARGET_32BIT && reload_completed"
    [(set (match_dup 3)
        (mult:SI (match_dup 1) (match_dup 2)))
     (set (match_dup 0)
                    (const_int 0)))
     (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
        (mult:SI (match_dup 1) (match_dup 2)))]
-   ""
+   "TARGET_32BIT"
    "@
     mullw. %0,%1,%2
     #"
                    (const_int 0)))
     (set (match_operand:SI 0 "gpc_reg_operand" "")
        (mult:SI (match_dup 1) (match_dup 2)))]
-   "reload_completed"
+   "TARGET_32BIT && reload_completed"
    [(set (match_dup 0)
        (mult:SI (match_dup 1) (match_dup 2)))
     (set (match_dup 3)
  
  (define_split
    [(set (match_operand:DI 0 "gpc_reg_operand" "")
 -      (match_operand:DI 1 "const_double_operand" ""))]
 +      (match_operand:DI 1 "const_scalar_int_operand" ""))]
    "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1"
    [(set (match_dup 0) (match_dup 2))
     (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
  
  (define_split
    [(set (match_operand:TI2 0 "int_reg_operand" "")
 -      (match_operand:TI2 1 "const_double_operand" ""))]
 +      (match_operand:TI2 1 "const_scalar_int_operand" ""))]
    "TARGET_POWERPC64
     && (VECTOR_MEM_NONE_P (<MODE>mode)
         || (reload_completed && INT_REGNO_P (REGNO (operands[0]))))"
                                       <MODE>mode);
    operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
                                       <MODE>mode);
 -  if (GET_CODE (operands[1]) == CONST_DOUBLE)
 +  if (CONST_WIDE_INT_P (operands[1]))
      {
 -      operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
 -      operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
 +      operands[4] = GEN_INT (CONST_WIDE_INT_ELT (operands[1], 1));
 +      operands[5] = GEN_INT (CONST_WIDE_INT_ELT (operands[1], 0));
      }
 -  else if (GET_CODE (operands[1]) == CONST_INT)
 +  else if (CONST_INT_P (operands[1]))
      {
        operands[4] = GEN_INT (- (INTVAL (operands[1]) < 0));
        operands[5] = operands[1];
diff --combined gcc/config/sh/sh.c
index 5a8a236d25f57b67599f4cbfb0b1cb8c48125fd7,167b615e37b1f57ddf9a312e678c7cd02bd64505..215d4cec6e5bd6e0578522d82f38f3bb0dc0ede1
@@@ -63,9 -63,6 +63,6 @@@ along with GCC; see the file COPYING3
  
  int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
  
- #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
- #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
  /* These are some macros to abstract register modes.  */
  #define CONST_OK_FOR_I10(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -512 \
                                 && ((HOST_WIDE_INT)(VALUE)) <= 511)
@@@ -174,7 -171,6 +171,6 @@@ static bool shmedia_space_reserved_for_
  
  static void split_branches (rtx);
  static int branch_dest (rtx);
- static void force_into (rtx, rtx);
  static void print_slot (rtx);
  static rtx add_constant (rtx, enum machine_mode, rtx);
  static void dump_table (rtx, rtx);
@@@ -1164,7 -1160,7 +1160,7 @@@ sh_print_operand (FILE *stream, rtx x, 
                                      DECL_ATTRIBUTES (current_function_decl));
        if (trapa_attr)
        fprintf (stream, "trapa #%ld",
 -               (long) TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (trapa_attr))));
 +               (long) tree_to_hwi (TREE_VALUE (TREE_VALUE (trapa_attr))));
        else if (sh_cfun_interrupt_handler_p ())
        {
          if (sh_cfun_resbank_handler_p ())
        if (REG_P (x) || GET_CODE (x) == SUBREG)
        {
          regno = true_regnum (x);
-         regno += FP_REGISTER_P (regno) ? 1 : LSW;
+         regno += FP_REGISTER_P (regno) ? 1 : SH_REG_LSW_OFFSET;
          fputs (reg_names[regno], (stream));
        }
        else if (MEM_P (x))
        {
-         x = adjust_address (x, SImode, 4 * LSW);
+         x = adjust_address (x, SImode, 4 * SH_REG_LSW_OFFSET);
          sh_print_operand_address (stream, XEXP (x, 0));
        }
        else
          if (mode == VOIDmode)
            mode = DImode;
          if (GET_MODE_SIZE (mode) >= 8)
-           sub = simplify_subreg (SImode, x, mode, 4 * LSW);
+           sub = simplify_subreg (SImode, x, mode, 4 * SH_REG_LSW_OFFSET);
          if (sub)
            sh_print_operand (stream, sub, 0);
          else
        if (REG_P (x) || GET_CODE (x) == SUBREG)
        {
          regno = true_regnum (x);
-         regno += FP_REGISTER_P (regno) ? 0 : MSW;
+         regno += FP_REGISTER_P (regno) ? 0 : SH_REG_MSW_OFFSET;
          fputs (reg_names[regno], (stream));
        }
        else if (MEM_P (x))
        {
-         x = adjust_address (x, SImode, 4 * MSW);
+         x = adjust_address (x, SImode, 4 * SH_REG_MSW_OFFSET);
          sh_print_operand_address (stream, XEXP (x, 0));
        }
        else
          if (mode == VOIDmode)
            mode = DImode;
          if (GET_MODE_SIZE (mode) >= 8)
-           sub = simplify_subreg (SImode, x, mode, 4 * MSW);
+           sub = simplify_subreg (SImode, x, mode, 4 * SH_REG_MSW_OFFSET);
          if (sub)
            sh_print_operand (stream, sub, 0);
          else
@@@ -1621,157 -1617,6 +1617,6 @@@ sh_encode_section_info (tree decl, rtx 
      SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FUNCVEC_FUNCTION;
  }
  
- /* Like force_operand, but guarantees that VALUE ends up in TARGET.  */
- static void
- force_into (rtx value, rtx target)
- {
-   value = force_operand (value, target);
-   if (! rtx_equal_p (value, target))
-     emit_insn (gen_move_insn (target, value));
- }
- /* Emit code to perform a block move.  Choose the best method.
-    OPERANDS[0] is the destination.
-    OPERANDS[1] is the source.
-    OPERANDS[2] is the size.
-    OPERANDS[3] is the alignment safe to use.  */
- bool
- expand_block_move (rtx *operands)
- {
-   int align = INTVAL (operands[3]);
-   int constp = (CONST_INT_P (operands[2]));
-   int bytes = (constp ? INTVAL (operands[2]) : 0);
-   if (! constp)
-     return false;
-   /* If we could use mov.l to move words and dest is word-aligned, we
-      can use movua.l for loads and still generate a relatively short
-      and efficient sequence.  */
-   if (TARGET_SH4A_ARCH && align < 4
-       && MEM_ALIGN (operands[0]) >= 32
-       && can_move_by_pieces (bytes, 32))
-     {
-       rtx dest = copy_rtx (operands[0]);
-       rtx src = copy_rtx (operands[1]);
-       /* We could use different pseudos for each copied word, but
-        since movua can only load into r0, it's kind of
-        pointless.  */
-       rtx temp = gen_reg_rtx (SImode);
-       rtx src_addr = copy_addr_to_reg (XEXP (src, 0));
-       int copied = 0;
-       while (copied + 4 <= bytes)
-       {
-         rtx to = adjust_address (dest, SImode, copied);
-         rtx from = adjust_automodify_address (src, BLKmode,
-                                               src_addr, copied);
-         set_mem_size (from, 4);
-         emit_insn (gen_movua (temp, from));
-         emit_move_insn (src_addr, plus_constant (Pmode, src_addr, 4));
-         emit_move_insn (to, temp);
-         copied += 4;
-       }
-       if (copied < bytes)
-       move_by_pieces (adjust_address (dest, BLKmode, copied),
-                       adjust_automodify_address (src, BLKmode,
-                                                  src_addr, copied),
-                       bytes - copied, align, 0);
-       return true;
-     }
-   /* If it isn't a constant number of bytes, or if it doesn't have 4 byte
-      alignment, or if it isn't a multiple of 4 bytes, then fail.  */
-   if (align < 4 || (bytes % 4 != 0))
-     return false;
-   if (TARGET_HARD_SH4)
-     {
-       if (bytes < 12)
-       return false;
-       else if (bytes == 12)
-       {
-         rtx func_addr_rtx = gen_reg_rtx (Pmode);
-         rtx r4 = gen_rtx_REG (SImode, 4);
-         rtx r5 = gen_rtx_REG (SImode, 5);
-         function_symbol (func_addr_rtx, "__movmemSI12_i4", SFUNC_STATIC);
-         force_into (XEXP (operands[0], 0), r4);
-         force_into (XEXP (operands[1], 0), r5);
-         emit_insn (gen_block_move_real_i4 (func_addr_rtx));
-         return true;
-       }
-       else if (! optimize_size)
-       {
-         const char *entry_name;
-         rtx func_addr_rtx = gen_reg_rtx (Pmode);
-         int dwords;
-         rtx r4 = gen_rtx_REG (SImode, 4);
-         rtx r5 = gen_rtx_REG (SImode, 5);
-         rtx r6 = gen_rtx_REG (SImode, 6);
-         entry_name = (bytes & 4 ? "__movmem_i4_odd" : "__movmem_i4_even");
-         function_symbol (func_addr_rtx, entry_name, SFUNC_STATIC);
-         force_into (XEXP (operands[0], 0), r4);
-         force_into (XEXP (operands[1], 0), r5);
-         dwords = bytes >> 3;
-         emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1)));
-         emit_insn (gen_block_lump_real_i4 (func_addr_rtx));
-         return true;
-       }
-       else
-       return false;
-     }
-   if (bytes < 64)
-     {
-       char entry[30];
-       rtx func_addr_rtx = gen_reg_rtx (Pmode);
-       rtx r4 = gen_rtx_REG (SImode, 4);
-       rtx r5 = gen_rtx_REG (SImode, 5);
-       sprintf (entry, "__movmemSI%d", bytes);
-       function_symbol (func_addr_rtx, entry, SFUNC_STATIC);
-       force_into (XEXP (operands[0], 0), r4);
-       force_into (XEXP (operands[1], 0), r5);
-       emit_insn (gen_block_move_real (func_addr_rtx));
-       return true;
-     }
-   /* This is the same number of bytes as a memcpy call, but to a different
-      less common function name, so this will occasionally use more space.  */
-   if (! optimize_size)
-     {
-       rtx func_addr_rtx = gen_reg_rtx (Pmode);
-       int final_switch, while_loop;
-       rtx r4 = gen_rtx_REG (SImode, 4);
-       rtx r5 = gen_rtx_REG (SImode, 5);
-       rtx r6 = gen_rtx_REG (SImode, 6);
-       function_symbol (func_addr_rtx, "__movmem", SFUNC_STATIC);
-       force_into (XEXP (operands[0], 0), r4);
-       force_into (XEXP (operands[1], 0), r5);
-       /* r6 controls the size of the move.  16 is decremented from it
-        for each 64 bytes moved.  Then the negative bit left over is used
-        as an index into a list of move instructions.  e.g., a 72 byte move
-        would be set up with size(r6) = 14, for one iteration through the
-        big while loop, and a switch of -2 for the last part.  */
-       final_switch = 16 - ((bytes / 4) % 16);
-       while_loop = ((bytes / 4) / 16 - 1) * 16;
-       emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
-       emit_insn (gen_block_lump_real (func_addr_rtx));
-       return true;
-     }
-   return false;
- }
  /* Prepare operands for a move define_expand; specifically, one of the
     operands must be in a register.  */
  void
@@@ -3314,6 -3159,35 +3159,35 @@@ and_xor_ior_costs (rtx x, int code
  static inline int
  addsubcosts (rtx x)
  {
+   if (GET_MODE (x) == SImode)
+     {
+       /* The addc or subc patterns will eventually become one or two
+        instructions.  Below are some costs for some of the patterns
+        which combine would reject because the costs of the individual
+        insns in the patterns are lower.
+        FIXME: It would be much easier if we had something like insn cost
+        attributes and the cost calculation machinery used those attributes
+        in the first place.  This would eliminate redundant recog-like C
+        code to calculate costs of complex patterns.  */
+       rtx op0 = XEXP (x, 0);
+       rtx op1 = XEXP (x, 1);
+       if (GET_CODE (x) == PLUS)
+       {
+         if (GET_CODE (op0) == AND
+             && XEXP (op0, 1) == const1_rtx
+             && (GET_CODE (op1) == PLUS
+                 || (GET_CODE (op1) == MULT && XEXP (op1, 1) == const2_rtx)))
+           return 1;
+         if (GET_CODE (op0) == MULT && XEXP (op0, 1) == const2_rtx
+             && GET_CODE (op1) == LSHIFTRT
+             && CONST_INT_P (XEXP (op1, 1)) && INTVAL (XEXP (op1, 1)) == 31)
+           return 1;
+       }
+     }
    /* On SH1-4 we have only max. SImode operations.
       Double the cost for modes > SImode.  */
    const int cost_scale = !TARGET_SHMEDIA
@@@ -8413,8 -8287,8 +8287,8 @@@ sh_builtin_saveregs (void
          emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (-UNITS_PER_WORD)));
          mem = change_address (regbuf, SFmode, fpregs);
          emit_move_insn (mem,
-                         gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + regno
-                                               - (TARGET_LITTLE_ENDIAN != 0)));
+                         gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode)
+                                              + regno - SH_REG_MSW_OFFSET));
        }
      }
    else
@@@ -9623,7 -9497,7 +9497,7 @@@ sh2a_handle_function_vector_handler_att
               name);
        *no_add_attrs = true;
      }
 -  else if (TREE_INT_CST_LOW (TREE_VALUE (args)) > 255)
 +  else if (tree_to_hwi (TREE_VALUE (args)) > 255)
      {
        /* The argument value must be between 0 to 255.  */
        warning (OPT_Wattributes,
@@@ -9672,7 -9546,7 +9546,7 @@@ sh2a_get_function_vector_number (rtx x
        {
          if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
            {
 -            num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list)));
 +            num = tree_to_hwi (TREE_VALUE (TREE_VALUE (list)));
              return num;
            }
  
diff --combined gcc/coverage.c
index 9c91f641953e3945deb7372a9d2ac5de57a77c0e,9b0fc8b3d1437c81d76bfaa5422a70d3196ea1bc..43f9c0cb6f13fa11022b10292ca6e85bfd149061
@@@ -554,12 -554,12 +554,12 @@@ unsigne
  coverage_compute_profile_id (struct cgraph_node *n)
  {
    expanded_location xloc
-     = expand_location (DECL_SOURCE_LOCATION (n->symbol.decl));
+     = expand_location (DECL_SOURCE_LOCATION (n->decl));
    unsigned chksum = xloc.line;
  
    chksum = coverage_checksum_string (chksum, xloc.file);
    chksum = coverage_checksum_string
-     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->symbol.decl)));
+     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
    if (first_global_object_name)
      chksum = coverage_checksum_string
        (chksum, first_global_object_name);
@@@ -830,7 -830,7 +830,7 @@@ build_fn_info (const struct coverage_da
  
        if (var)
          count
 -          = tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))), 0)
 +          = tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))))
            + 1;
  
        CONSTRUCTOR_APPEND_ELT (ctr, TYPE_FIELDS (ctr_type),
diff --combined gcc/cp/call.c
index c0eb1d6b82495cf181a353af9b9d3d347d829172,961ee2c22784fde198458b24a10a9323829917cd..e2907badc3aafc8ae125308dba468c2c7a9814e1
@@@ -38,7 -38,6 +38,7 @@@ along with GCC; see the file COPYING3
  #include "c-family/c-objc.h"
  #include "timevar.h"
  #include "cgraph.h"
 +#include "wide-int.h"
  
  /* The various kinds of conversion.  */
  
@@@ -942,7 -941,7 +942,7 @@@ build_array_conv (tree type, tree ctor
  
    if (TYPE_DOMAIN (type))
      {
 -      unsigned HOST_WIDE_INT alen = tree_low_cst (array_type_nelts_top (type), 1);
 +      unsigned HOST_WIDE_INT alen = tree_to_uhwi (array_type_nelts_top (type));
        if (alen < len)
        return NULL;
      }
@@@ -6493,7 -6492,8 +6493,7 @@@ type_passed_as (tree type
    else if (targetm.calls.promote_prototypes (type)
           && INTEGRAL_TYPE_P (type)
           && COMPLETE_TYPE_P (type)
 -         && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
 -                                 TYPE_SIZE (integer_type_node)))
 +         && INT_CST_LT (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
      type = integer_type_node;
  
    return type;
@@@ -6533,7 -6533,8 +6533,7 @@@ convert_for_arg_passing (tree type, tre
    else if (targetm.calls.promote_prototypes (type)
           && INTEGRAL_TYPE_P (type)
           && COMPLETE_TYPE_P (type)
 -         && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
 -                                 TYPE_SIZE (integer_type_node)))
 +         && INT_CST_LT (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
      val = cp_perform_integral_promotions (val, complain);
    if ((complain & tf_warning)
        && warn_suggest_attribute_format)
@@@ -6629,7 -6630,7 +6629,7 @@@ mark_versions_used (tree fn
    it_v = node_v->next;
    while (it_v != NULL)
      {
-       mark_used (it_v->this_node->symbol.decl);
+       mark_used (it_v->this_node->decl);
        it_v = it_v->next;
      }
  }
@@@ -7111,8 -7112,9 +7111,9 @@@ build_over_call (struct z_candidate *ca
        mark_versions_used (fn);
      }
  
-   if (!already_used)
-     mark_used (fn);
+   if (!already_used
+       && !mark_used (fn))
+     return error_mark_node;
  
    if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
        /* Don't mess with virtual lookup in fold_non_dependent_expr; virtual
@@@ -9272,6 -9274,9 +9273,9 @@@ set_up_extended_ref_temp (tree decl, tr
            static_aggregates = tree_cons (NULL_TREE, var,
                                           static_aggregates);
        }
+       else
+       /* Check whether the dtor is callable.  */
+       cxx_maybe_build_cleanup (var, tf_warning_or_error);
      }
  
    *initp = init;
diff --combined gcc/cp/class.c
index b90ef3fb8ed8a5fab0f2b133e34bf050edcf0599,64681ba44df824d442ba3411c36576bb4ad7d18b..a0c3ab7e72b9d730992485708a77df505790842b
@@@ -36,7 -36,6 +36,7 @@@ along with GCC; see the file COPYING3
  #include "splay-tree.h"
  #include "pointer-set.h"
  #include "hash-table.h"
 +#include "wide-int.h"
  
  /* The number of nested classes being processed.  If we are not in the
     scope of any class, this is zero.  */
@@@ -4675,15 -4674,8 +4675,8 @@@ deduce_noexcept_on_destructors (tree t
    if (!CLASSTYPE_METHOD_VEC (t))
      return;
  
-   bool saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
-   /* Avoid early exit from synthesized_method_walk (c++/57645).  */
-   TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = true;
    for (tree fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
      deduce_noexcept_on_destructor (OVL_CURRENT (fns));
-   TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = saved_nontrivial_dtor;
  }
  
  /* Subroutine of set_one_vmethod_tm_attributes.  Search base classes
@@@ -4885,7 -4877,8 +4878,8 @@@ user_provided_p (tree fn
      return true;
    else
      return (!DECL_ARTIFICIAL (fn)
-           && !DECL_DEFAULTED_IN_CLASS_P (fn));
+           && !(DECL_INITIALIZED_IN_CLASS_P (fn)
+                && (DECL_DEFAULTED_FN (fn) || DECL_DELETED_FN (fn))));
  }
  
  /* Returns true iff class T has a user-provided constructor.  */
@@@ -5150,7 -5143,7 +5144,7 @@@ type_has_user_declared_move_assign (tre
  }
  
  /* Nonzero if we need to build up a constructor call when initializing an
-    object of this class, either because it has a user-provided constructor
+    object of this class, either because it has a user-declared constructor
     or because it doesn't have a default constructor (so we need to give an
     error if no initializer is provided).  Use TYPE_NEEDS_CONSTRUCTING when
     what you care about is whether or not an object can be produced by a
@@@ -5166,8 -5159,50 +5160,50 @@@ type_build_ctor_call (tree t
    if (TYPE_NEEDS_CONSTRUCTING (t))
      return true;
    inner = strip_array_types (t);
-   return (CLASS_TYPE_P (inner) && !TYPE_HAS_DEFAULT_CONSTRUCTOR (inner)
-         && !ANON_AGGR_TYPE_P (inner));
+   if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner))
+     return false;
+   if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (inner))
+     return true;
+   if (cxx_dialect < cxx11)
+     return false;
+   /* A user-declared constructor might be private, and a constructor might
+      be trivial but deleted.  */
+   for (tree fns = lookup_fnfields_slot (inner, complete_ctor_identifier);
+        fns; fns = OVL_NEXT (fns))
+     {
+       tree fn = OVL_CURRENT (fns);
+       if (!DECL_ARTIFICIAL (fn)
+         || DECL_DELETED_FN (fn))
+       return true;
+     }
+   return false;
+ }
+ /* Like type_build_ctor_call, but for destructors.  */
+ bool
+ type_build_dtor_call (tree t)
+ {
+   tree inner;
+   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
+     return true;
+   inner = strip_array_types (t);
+   if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner)
+       || !COMPLETE_TYPE_P (inner))
+     return false;
+   if (cxx_dialect < cxx11)
+     return false;
+   /* A user-declared destructor might be private, and a destructor might
+      be trivial but deleted.  */
+   for (tree fns = lookup_fnfields_slot (inner, complete_dtor_identifier);
+        fns; fns = OVL_NEXT (fns))
+     {
+       tree fn = OVL_CURRENT (fns);
+       if (!DECL_ARTIFICIAL (fn)
+         || DECL_DELETED_FN (fn))
+       return true;
+     }
+   return false;
  }
  
  /* Remove all zero-width bit-fields from T.  */
@@@ -5790,7 -5825,7 +5826,7 @@@ end_of_class (tree t, int include_virtu
        continue;
  
        offset = end_of_base (base_binfo);
 -      if (INT_CST_LT_UNSIGNED (result, offset))
 +      if (INT_CST_LT (result, offset))
        result = offset;
      }
  
         vec_safe_iterate (vbases, i, &base_binfo); i++)
        {
        offset = end_of_base (base_binfo);
 -      if (INT_CST_LT_UNSIGNED (result, offset))
 +      if (INT_CST_LT (result, offset))
          result = offset;
        }
  
@@@ -5880,7 -5915,7 +5916,7 @@@ include_empty_classes (record_layout_in
                      CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
    rli_size = rli_size_unit_so_far (rli);
    if (TREE_CODE (rli_size) == INTEGER_CST
 -      && INT_CST_LT_UNSIGNED (rli_size, eoc))
 +      && INT_CST_LT (rli_size, eoc))
      {
        if (!abi_version_at_least (2))
        /* In version 1 of the ABI, the size of a class that ends with
@@@ -6132,7 -6167,7 +6168,7 @@@ layout_class_type (tree t, tree *virtua
        {
          unsigned HOST_WIDE_INT width;
          tree ftype = TREE_TYPE (field);
 -        width = tree_low_cst (DECL_SIZE (field), /*unsignedp=*/1);
 +        width = tree_to_uhwi (DECL_SIZE (field));
          if (width != TYPE_PRECISION (ftype))
            {
              TREE_TYPE (field)
@@@ -8004,7 -8039,7 +8040,7 @@@ dump_class_hierarchy_r (FILE *stream
    igo = TREE_CHAIN (binfo);
  
    fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
 -         tree_low_cst (BINFO_OFFSET (binfo), 0));
 +         tree_to_shwi (BINFO_OFFSET (binfo)));
    if (is_empty_class (BINFO_TYPE (binfo)))
      fprintf (stream, " empty");
    else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo)))
@@@ -8080,10 -8115,10 +8116,10 @@@ dump_class_hierarchy_1 (FILE *stream, i
  {
    fprintf (stream, "Class %s\n", type_as_string (t, TFF_PLAIN_IDENTIFIER));
    fprintf (stream, "   size=%lu align=%lu\n",
 -         (unsigned long)(tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT),
 +         (unsigned long)(tree_to_shwi (TYPE_SIZE (t)) / BITS_PER_UNIT),
           (unsigned long)(TYPE_ALIGN (t) / BITS_PER_UNIT));
    fprintf (stream, "   base size=%lu base align=%lu\n",
 -         (unsigned long)(tree_low_cst (TYPE_SIZE (CLASSTYPE_AS_BASE (t)), 0)
 +         (unsigned long)(tree_to_shwi (TYPE_SIZE (CLASSTYPE_AS_BASE (t)))
                           / BITS_PER_UNIT),
           (unsigned long)(TYPE_ALIGN (CLASSTYPE_AS_BASE (t))
                           / BITS_PER_UNIT));
@@@ -8120,7 -8155,7 +8156,7 @@@ dump_array (FILE * stream, tree decl
    HOST_WIDE_INT elt;
    tree size = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (decl)));
  
 -  elt = (tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl))), 0)
 +  elt = (tree_to_shwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl))))
         / BITS_PER_UNIT);
    fprintf (stream, "%s:", decl_as_string (decl, TFF_PLAIN_IDENTIFIER));
    fprintf (stream, " %s entries",
@@@ -8209,10 -8244,10 +8245,10 @@@ dump_thunk (FILE *stream, int indent, t
        /*NOP*/;
        else if (DECL_THIS_THUNK_P (thunk))
        fprintf (stream, " vcall="  HOST_WIDE_INT_PRINT_DEC,
 -               tree_low_cst (virtual_adjust, 0));
 +               tree_to_shwi (virtual_adjust));
        else
        fprintf (stream, " vbase=" HOST_WIDE_INT_PRINT_DEC "(%s)",
 -               tree_low_cst (BINFO_VPTR_FIELD (virtual_adjust), 0),
 +               tree_to_shwi (BINFO_VPTR_FIELD (virtual_adjust)),
                 type_as_string (BINFO_TYPE (virtual_adjust), TFF_SCOPE));
        if (THUNK_ALIAS (thunk))
        fprintf (stream, " alias to %p", (void *)THUNK_ALIAS (thunk));
diff --combined gcc/cp/cp-tree.h
index 713e001730cdf22846ee0c10d55ffd740d4642b9,fd79adbd3573fd26bb0b6f0ad5b3f4831905b0d0..7a1c900193a9314ff12b84afcc42400632644706
@@@ -116,6 -116,7 +116,7 @@@ c-common.h, not after
     6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
        DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL)
        TYPE_MARKED_P (in _TYPE)
+       RANGE_FOR_IVDEP (in RANGE_FOR_STMT)
  
     Usage of TYPE_LANG_FLAG_?:
     0: TYPE_DEPENDENT_P
@@@ -2804,7 -2805,7 +2805,7 @@@ extern void decl_shadowed_for_var_inser
  
  /* The number of levels of template parameters given by NODE.  */
  #define TMPL_PARMS_DEPTH(NODE) \
 -  ((HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_PURPOSE (NODE)))
 +  ((HOST_WIDE_INT) tree_to_hwi (TREE_PURPOSE (NODE)))
  
  /* The TEMPLATE_DECL instantiated or specialized by NODE.  This
     TEMPLATE_DECL will be the immediate parent, not the most general
@@@ -3688,7 -3689,7 +3689,7 @@@ more_aggr_init_expr_args_p (const aggr_
  /* Accessor macros for C++ template decl nodes.  */
  
  /* The DECL_TEMPLATE_PARMS are a list.  The TREE_PURPOSE of each node
 -   is a INT_CST whose TREE_INT_CST_LOW indicates the level of the
 +   is a INT_CST whose tree_to_hwi indicates the level of the
     template parameters, with 1 being the outermost set of template
     parameters.  The TREE_VALUE is a vector, whose elements are the
     template parameters at each level.  Each element in the vector is a
  #define RANGE_FOR_EXPR(NODE)  TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 1)
  #define RANGE_FOR_BODY(NODE)  TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 2)
  #define RANGE_FOR_SCOPE(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 3)
+ #define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE))
  
  #define SWITCH_STMT_COND(NODE)        TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0)
  #define SWITCH_STMT_BODY(NODE)        TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 1)
@@@ -4321,7 -4323,7 +4323,7 @@@ extern int comparing_specializations
     sizeof can be nested.  */
  
  extern int cp_unevaluated_operand;
- extern tree cp_convert_range_for (tree, tree, tree);
+ extern tree cp_convert_range_for (tree, tree, tree, bool);
  extern bool parsing_nsdmi (void);
  
  /* in pt.c  */
@@@ -5115,6 -5117,7 +5117,7 @@@ extern bool type_has_move_assign                (tree
  extern bool type_has_user_declared_move_constructor (tree);
  extern bool type_has_user_declared_move_assign(tree);
  extern bool type_build_ctor_call              (tree);
+ extern bool type_build_dtor_call              (tree);
  extern void explain_non_literal_class         (tree);
  extern void defaulted_late_check              (tree);
  extern bool defaultable_fn_check              (tree);
@@@ -5670,16 -5673,16 +5673,16 @@@ extern void begin_else_clause                        (tree)
  extern void finish_else_clause                        (tree);
  extern void finish_if_stmt                    (tree);
  extern tree begin_while_stmt                  (void);
- extern void finish_while_stmt_cond            (tree, tree);
+ extern void finish_while_stmt_cond            (tree, tree, bool);
  extern void finish_while_stmt                 (tree);
  extern tree begin_do_stmt                     (void);
  extern void finish_do_body                    (tree);
- extern void finish_do_stmt                    (tree, tree);
+ extern void finish_do_stmt                    (tree, tree, bool);
  extern tree finish_return_stmt                        (tree);
  extern tree begin_for_scope                   (tree *);
  extern tree begin_for_stmt                    (tree, tree);
  extern void finish_for_init_stmt              (tree);
- extern void finish_for_cond                   (tree, tree);
+ extern void finish_for_cond                   (tree, tree, bool);
  extern void finish_for_expr                   (tree, tree);
  extern void finish_for_stmt                   (tree);
  extern tree begin_range_for_stmt              (tree, tree);
diff --combined gcc/cp/decl.c
index 84271fef4dd72b871931b4b589e3dc5883173673,e662764da8598a671aa89527a3a074531128d124..81a35004730b404c6f8e842e088c6e5660a43bd8
@@@ -45,6 -45,7 +45,7 @@@ along with GCC; see the file COPYING3
  #include "c-family/c-objc.h"
  #include "c-family/c-pragma.h"
  #include "c-family/c-target.h"
+ #include "c-family/c-ubsan.h"
  #include "diagnostic.h"
  #include "intl.h"
  #include "debug.h"
@@@ -53,7 -54,6 +54,7 @@@
  #include "splay-tree.h"
  #include "plugin.h"
  #include "cgraph.h"
 +#include "wide-int.h"
  
  /* Possible cases of bad specifiers type used by bad_specifiers. */
  enum bad_spec_place {
@@@ -4804,8 -4804,7 +4805,8 @@@ check_array_designated_initializer (con
        if (TREE_CODE (ce->index) == INTEGER_CST)
        {
          /* A C99 designator is OK if it matches the current index.  */
 -        if (TREE_INT_CST_LOW (ce->index) == index)
 +        if (tree_fits_uhwi_p (ce->index) 
 +            && tree_to_uhwi (ce->index) == index)
            return true;
          else
            sorry ("non-trivial designated initializers not supported");
@@@ -5092,11 -5091,12 +5093,11 @@@ reshape_init_array_1 (tree elt_type, tr
        if (integer_all_onesp (max_index))
        return new_init;
  
 -      if (host_integerp (max_index, 1))
 -      max_index_cst = tree_low_cst (max_index, 1);
 +      if (tree_fits_uhwi_p (max_index))
 +      max_index_cst = tree_to_uhwi (max_index);
        /* sizetype is sign extended, not zero extended.  */
        else
 -      max_index_cst = tree_low_cst (fold_convert (size_type_node, max_index),
 -                                    1);
 +      max_index_cst = tree_to_uhwi (fold_convert (size_type_node, max_index));
      }
  
    /* Loop until there are no more initializers.  */
@@@ -6400,21 -6400,6 +6401,6 @@@ cp_finish_decl (tree decl, tree init, b
           && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
      error ("non-static data member %qD has Java class type", decl);
  
-   if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
-     {
-       /* If the VLA bound is larger than half the address space, or less
-        than zero, throw std::bad_array_length.  */
-       tree max = convert (ssizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
-       /* C++1y says we should throw for length <= 0, but we have
-        historically supported zero-length arrays.  Let's treat that as an
-        extension to be disabled by -std=c++NN.  */
-       int lower = flag_iso ? 0 : -1;
-       tree comp = build2 (LT_EXPR, boolean_type_node, max, ssize_int (lower));
-       comp = build3 (COND_EXPR, void_type_node, comp,
-                    throw_bad_array_length (), void_zero_node);
-       finish_expr_stmt (comp);
-     }
    /* Add this declaration to the statement-tree.  This needs to happen
       after the call to check_initializer so that the DECL_EXPR for a
       reference temp is added before the DECL_EXPR for the reference itself.  */
@@@ -6898,7 -6883,11 +6884,11 @@@ expand_static_init (tree decl, tree ini
    /* Some variables require no dynamic initialization.  */
    if (!init
        && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
-     return;
+     {
+       /* Make sure the destructor is callable.  */
+       cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+       return;
+     }
  
    if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
        && !DECL_FUNCTION_SCOPE_P (decl))
@@@ -8380,6 -8369,7 +8370,7 @@@ compute_array_index_type (tree name, tr
        {
          /* A variable sized array.  */
          itype = variable_size (itype);
          if (TREE_CODE (itype) != SAVE_EXPR)
            {
              /* Look for SIZEOF_EXPRs in itype and fold them, otherwise
              if (found)
                itype = variable_size (fold (newitype));
            }
+         stabilize_vla_size (itype);
+         if (cxx_dialect >= cxx1y)
+           {
+             /* If the VLA bound is larger than half the address space,
+                or less than zero, throw std::bad_array_length.  */
+             tree comp = build2 (LT_EXPR, boolean_type_node, itype,
+                                 ssize_int (-1));
+             comp = build3 (COND_EXPR, void_type_node, comp,
+                            throw_bad_array_length (), void_zero_node);
+             finish_expr_stmt (comp);
+           }
+         else if (flag_sanitize & SANITIZE_VLA)
+           {
+             /* From C++1y onwards, we throw an exception on a negative
+                length size of an array; see above.  */
+             /* We have to add 1 -- in the ubsan routine we generate
+                LE_EXPR rather than LT_EXPR.  */
+             tree t = fold_build2 (PLUS_EXPR, TREE_TYPE (itype), itype,
+                                   build_one_cst (TREE_TYPE (itype)));
+             t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t),
+                              ubsan_instrument_vla (input_location, t), t);
+             finish_expr_stmt (t);
+           }
        }
        /* Make sure that there was no overflow when creating to a signed
         index type.  (For example, on a 32-bit machine, an array with
@@@ -9791,12 -9807,8 +9808,8 @@@ grokdeclarator (const cp_declarator *de
              && (decl_context == NORMAL || decl_context == FIELD)
              && at_function_scope_p ()
              && variably_modified_type_p (type, NULL_TREE))
-           {
-             /* First break out any side-effects.  */
-             stabilize_vla_size (TYPE_SIZE (type));
-             /* And then force evaluation of the SAVE_EXPR.  */
-             finish_expr_stmt (TYPE_SIZE (type));
-           }
+           /* Force evaluation of the SAVE_EXPR.  */
+           finish_expr_stmt (TYPE_SIZE (type));
  
          if (declarator->kind == cdk_reference)
            {
        }
      }
  
-   /* We need to stabilize side-effects in VLA sizes for regular array
-      declarations too, not just pointers to arrays.  */
-   if (type != error_mark_node && !TYPE_NAME (type)
-       && (decl_context == NORMAL || decl_context == FIELD)
-       && at_function_scope_p ()
-       && variably_modified_type_p (type, NULL_TREE))
-     stabilize_vla_size (TYPE_SIZE (type));
    /* A `constexpr' specifier used in an object declaration declares
       the object as `const'.  */
    if (constexpr_p && innermost_code != cdk_function)
      {
        error ("size of array %qs is too large", name);
        /* If we proceed with the array type as it is, we'll eventually
 -       crash in tree_low_cst().  */
 +       crash in tree_to_uhwi ().  */
        type = error_mark_node;
      }
  
@@@ -12672,9 -12676,9 +12677,9 @@@ finish_enum_value_list (tree enumtype
         enumeration.  We must do this before the type of MINNODE and
         MAXNODE are transformed, since tree_int_cst_min_precision relies
         on the TREE_TYPE of the value it is passed.  */
 -      bool unsignedp = tree_int_cst_sgn (minnode) >= 0;
 -      int lowprec = tree_int_cst_min_precision (minnode, unsignedp);
 -      int highprec = tree_int_cst_min_precision (maxnode, unsignedp);
 +      signop sgn = tree_int_cst_sgn (minnode) >= 0 ? UNSIGNED : SIGNED;
 +      int lowprec = tree_int_cst_min_precision (minnode, sgn);
 +      int highprec = tree_int_cst_min_precision (maxnode, sgn);
        int precision = MAX (lowprec, highprec);
        unsigned int itk;
        bool use_short_enum;
            underlying_type = integer_types[itk];
            if (underlying_type != NULL_TREE
              && TYPE_PRECISION (underlying_type) >= precision
 -              && TYPE_UNSIGNED (underlying_type) == unsignedp)
 +              && TYPE_SIGN (underlying_type) == sgn)
              break;
          }
        if (itk == itk_none)
        = build_distinct_type_copy (underlying_type);
        TYPE_PRECISION (ENUM_UNDERLYING_TYPE (enumtype)) = precision;
        set_min_and_max_values_for_integral_type
 -        (ENUM_UNDERLYING_TYPE (enumtype), precision, unsignedp);
 +        (ENUM_UNDERLYING_TYPE (enumtype), precision, sgn);
  
        /* If -fstrict-enums, still constrain TYPE_MIN/MAX_VALUE.  */
        if (flag_strict_enums)
 -      set_min_and_max_values_for_integral_type (enumtype, precision,
 -                                                unsignedp);
 +      set_min_and_max_values_for_integral_type (enumtype, precision, sgn);
      }
    else
      underlying_type = ENUM_UNDERLYING_TYPE (enumtype);
@@@ -12881,14 -12886,14 +12886,14 @@@ build_enumerator (tree name, tree value
                value = error_mark_node;
              else
                {
 -                double_int di = TREE_INT_CST (prev_value)
 -                                .add_with_sign (double_int_one,
 -                                                false, &overflowed);
 +                tree type = TREE_TYPE (prev_value);
 +                signop sgn = TYPE_SIGN (type);
 +                widest_int wi = wi::add (wi::to_widest (prev_value), 1, sgn,
 +                                         &overflowed);
                  if (!overflowed)
                    {
 -                    tree type = TREE_TYPE (prev_value);
 -                    bool pos = TYPE_UNSIGNED (type) || !di.is_negative ();
 -                    if (!double_int_fits_to_tree_p (type, di))
 +                    bool pos = !wi::neg_p (wi, sgn);
 +                    if (!wi::fits_to_tree_p (wi, type))
                        {
                          unsigned int itk;
                          for (itk = itk_int; itk != itk_none; itk++)
                              type = integer_types[itk];
                              if (type != NULL_TREE
                                  && (pos || !TYPE_UNSIGNED (type))
 -                                && double_int_fits_to_tree_p (type, di))
 +                                && wi::fits_to_tree_p (wi, type))
                                break;
                            }
                          if (type && cxx_dialect < cxx11
@@@ -12908,7 -12913,7 +12913,7 @@@ incremented enumerator value is too lar
                      if (type == NULL_TREE)
                        overflowed = true;
                      else
 -                      value = double_int_to_tree (type, di);
 +                      value = wide_int_to_tree (type, wi);
                    }
  
                  if (overflowed)
@@@ -14296,11 -14301,9 +14301,9 @@@ cxx_maybe_build_cleanup (tree decl, tsu
      }
    /* Handle ordinary C++ destructors.  */
    type = TREE_TYPE (decl);
-   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+   if (type_build_dtor_call (type))
      {
-       int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
-       bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
-                        && CLASSTYPE_VBASECLASSES (type));
+       int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR;
        tree addr;
        tree call;
  
        else
        addr = build_address (decl);
  
-       /* Optimize for space over speed here.  */
-       if (!has_vbases || flag_expensive_optimizations)
-       flags |= LOOKUP_NONVIRTUAL;
        call = build_delete (TREE_TYPE (addr), addr,
                           sfk_complete_destructor, flags, 0, complain);
        if (call == error_mark_node)
        cleanup = error_mark_node;
+       else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+       /* Discard the call.  */;
        else if (cleanup)
        cleanup = cp_build_compound_expr (cleanup, call, complain);
        else
diff --combined gcc/cp/error.c
index 1627afab95d3b98ab38284a2d08961d5abcd432b,5f997c3ed2924a04617a01af167ba068c4b226de..0ad9f0722db1d0c8f61d14fcb7dfe3e3d2229d45
@@@ -851,8 -851,8 +851,8 @@@ dump_type_suffix (cxx_pretty_printer *p
          tree max = TYPE_MAX_VALUE (dtype);
          if (integer_all_onesp (max))
            pp_character (pp, '0');
 -        else if (host_integerp (max, 0))
 -          pp_wide_integer (pp, tree_low_cst (max, 0) + 1);
 +        else if (tree_fits_shwi_p (max))
 +          pp_wide_integer (pp, tree_to_shwi (max) + 1);
          else
            {
              STRIP_NOPS (max);
@@@ -1853,7 -1853,7 +1853,7 @@@ static tre
  resolve_virtual_fun_from_obj_type_ref (tree ref)
  {
    tree obj_type = TREE_TYPE (OBJ_TYPE_REF_OBJECT (ref));
 -  HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
 +  HOST_WIDE_INT index = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (ref));
    tree fun = BINFO_VIRTUALS (TYPE_BINFO (TREE_TYPE (obj_type)));
    while (index)
      {
@@@ -2285,7 -2285,7 +2285,7 @@@ dump_expr (cxx_pretty_printer *pp, tre
              pp_cxx_right_paren (pp);
              break;
            }
 -        else if (host_integerp (idx, 0))
 +        else if (tree_fits_shwi_p (idx))
            {
              tree virtuals;
              unsigned HOST_WIDE_INT n;
              t = TYPE_METHOD_BASETYPE (t);
              virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
  
 -            n = tree_low_cst (idx, 0);
 +            n = tree_to_shwi (idx);
  
              /* Map vtable index back one, to allow for the null pointer to
                 member.  */
@@@ -2998,6 -2998,15 +2998,15 @@@ cv_to_string (tree p, int v
    return pp_ggc_formatted_text (cxx_pp);
  }
  
+ static const char *
+ eh_spec_to_string (tree p, int /*v*/)
+ {
+   int flags = 0;
+   reinit_cxx_pp ();
+   dump_exception_spec (cxx_pp, p, flags);
+   return pp_ggc_formatted_text (cxx_pp);
+ }
  /* Langhook for print_error_function.  */
  void
  cxx_print_error_function (diagnostic_context *context, const char *file,
@@@ -3379,8 -3388,10 +3388,10 @@@ maybe_print_constexpr_context (diagnost
     %O binary operator.
     %P   function parameter whose position is indicated by an integer.
     %Q assignment operator.
+    %S   substitution (template + args)
     %T   type.
-    %V   cv-qualifier.  */
+    %V   cv-qualifier.
+    %X   exception-specification.  */
  static bool
  cp_printer (pretty_printer *pp, text_info *text, const char *spec,
            int precision, bool wide, bool set_locus, bool verbose)
      case 'S': result = subst_to_string (next_tree);           break;
      case 'T': result = type_to_string (next_tree, verbose);   break;
      case 'V': result = cv_to_string (next_tree, verbose);     break;
+     case 'X': result = eh_spec_to_string (next_tree, verbose);  break;
  
      case 'K':
        percent_K_format (text);
diff --combined gcc/cp/init.c
index 17d320db072b7bebe39ae45ae41209f5c8d31413,85732ff3af14926abc029ae2457853feb76505a5..23c449ea85d99bfb128d5c2afe3a04e52454d7bb
@@@ -28,7 -28,6 +28,7 @@@ along with GCC; see the file COPYING3
  #include "cp-tree.h"
  #include "flags.h"
  #include "target.h"
 +#include "wide-int.h"
  
  static bool begin_init_stmts (tree *, tree *);
  static tree finish_init_stmts (bool, tree, tree);
@@@ -313,60 -312,55 +313,55 @@@ build_value_init (tree type, tsubst_fla
  
       To value-initialize an object of type T means:
  
-      - if T is a class type (clause 9) with a user-provided constructor
-        (12.1), then the default constructor for T is called (and the
-        initialization is ill-formed if T has no accessible default
-        constructor);
+      - if T is a class type (clause 9) with either no default constructor
+        (12.1) or a default constructor that is user-provided or deleted,
+        then then the object is default-initialized;
  
-      - if T is a non-union class type without a user-provided constructor,
-        then every non-static data member and base-class component of T is
-        value-initialized;92)
+      - if T is a (possibly cv-qualified) class type without a user-provided
+        or deleted default constructor, then the object is zero-initialized
+        and the semantic constraints for default-initialization are checked,
+        and if T has a non-trivial default constructor, the object is
+        default-initialized;
  
       - if T is an array type, then each element is value-initialized;
  
       - otherwise, the object is zero-initialized.
  
       A program that calls for default-initialization or
-      value-initialization of an entity of reference type is ill-formed.
-      92) Value-initialization for such a class object may be implemented by
-      zero-initializing the object and then calling the default
-      constructor.  */
+      value-initialization of an entity of reference type is ill-formed.  */
  
    /* The AGGR_INIT_EXPR tweaking below breaks in templates.  */
    gcc_assert (!processing_template_decl
              || (SCALAR_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE));
  
-   if (CLASS_TYPE_P (type))
+   if (type_build_ctor_call (type))
      {
-       /* Instead of the above, only consider the user-providedness of the
-        default constructor itself so value-initializing a class with an
-        explicitly defaulted default constructor and another user-provided
-        constructor works properly (c++std-core-19883).  */
-       if (type_has_user_provided_default_constructor (type)
-         || (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)
-             && type_has_user_provided_constructor (type)))
-       return build_aggr_init_expr
-         (type,
-          build_special_member_call (NULL_TREE, complete_ctor_identifier,
-                                     NULL, type, LOOKUP_NORMAL,
-                                     complain));
+       tree ctor = build_aggr_init_expr
+       (type,
+        build_special_member_call (NULL_TREE, complete_ctor_identifier,
+                                   NULL, type, LOOKUP_NORMAL,
+                                   complain));
+       if (ctor == error_mark_node
+         || type_has_user_provided_default_constructor (type))
+       return ctor;
        else if (TYPE_HAS_COMPLEX_DFLT (type))
        {
          /* This is a class that needs constructing, but doesn't have
             a user-provided constructor.  So we need to zero-initialize
             the object and then call the implicitly defined ctor.
             This will be handled in simplify_aggr_init_expr.  */
-         tree ctor = build_special_member_call
-           (NULL_TREE, complete_ctor_identifier,
-            NULL, type, LOOKUP_NORMAL, complain);
-         ctor = build_aggr_init_expr (type, ctor);
-         if (ctor != error_mark_node)
-           AGGR_INIT_ZERO_FIRST (ctor) = 1;
+         AGGR_INIT_ZERO_FIRST (ctor) = 1;
          return ctor;
        }
      }
-   return build_value_init_noctor (type, complain);
+   /* Discard any access checking during subobject initialization;
+      the checks are implied by the call to the ctor which we have
+      verified is OK (cpp0x/defaulted46.C).  */
+   push_deferring_access_checks (dk_deferred);
+   tree r = build_value_init_noctor (type, complain);
+   pop_deferring_access_checks ();
+   return r;
  }
  
  /* Like build_value_init, but don't call the constructor for TYPE.  Used
@@@ -504,14 -498,15 +499,15 @@@ perform_target_ctor (tree init
    finish_expr_stmt (build_aggr_init (decl, init,
                                     LOOKUP_NORMAL|LOOKUP_DELEGATING_CONS,
                                     tf_warning_or_error));
-   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+   if (type_build_dtor_call (type))
      {
        tree expr = build_delete (type, decl, sfk_complete_destructor,
                                LOOKUP_NORMAL
                                |LOOKUP_NONVIRTUAL
                                |LOOKUP_DESTRUCTOR,
                                0, tf_warning_or_error);
-       if (expr != error_mark_node)
+       if (expr != error_mark_node
+         && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
        finish_eh_cleanup (expr);
      }
  }
@@@ -733,7 -728,7 +729,7 @@@ perform_member_init (tree member, tree 
                                                tf_warning_or_error));
      }
  
-   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+   if (type_build_dtor_call (type))
      {
        tree expr;
  
                           LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
                           tf_warning_or_error);
  
-       if (expr != error_mark_node)
+       if (expr != error_mark_node
+         && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
        finish_eh_cleanup (expr);
      }
  }
@@@ -1193,7 -1189,7 +1190,7 @@@ expand_cleanup_for_base (tree binfo, tr
  {
    tree expr;
  
-   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
+   if (!type_build_dtor_call (BINFO_TYPE (binfo)))
      return;
  
    /* Call the destructor.  */
                                    binfo,
                                    LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                      tf_warning_or_error);
+   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
+     return;
    if (flag)
      expr = fold_build3_loc (input_location,
                        COND_EXPR, void_type_node,
@@@ -2242,10 -2242,10 +2243,10 @@@ build_new_1 (vec<tree, va_gc> **placeme
    /* For arrays, a bounds checks on the NELTS parameter. */
    tree outer_nelts_check = NULL_TREE;
    bool outer_nelts_from_type = false;
 -  double_int inner_nelts_count = double_int_one;
 +  offset_int inner_nelts_count = 1;
    tree alloc_call, alloc_expr;
    /* Size of the inner array elements. */
 -  double_int inner_size;
 +  offset_int inner_size;
    /* The address returned by the call to "operator new".  This node is
       a VAR_DECL and is therefore reusable.  */
    tree alloc_node;
        if (TREE_CODE (inner_nelts_cst) == INTEGER_CST)
        {
          bool overflow;
 -        double_int result = TREE_INT_CST (inner_nelts_cst)
 -                            .mul_with_sign (inner_nelts_count,
 -                                            false, &overflow);
 +        offset_int result = wi::mul (wi::to_offset (inner_nelts_cst),
 +                                     inner_nelts_count, SIGNED, &overflow);
          if (overflow)
            {
              if (complain & tf_error)
  
    is_initialized = (type_build_ctor_call (elt_type) || *init != NULL);
  
-   if (*init == NULL)
+   if (*init == NULL && cxx_dialect < cxx11)
      {
        bool maybe_uninitialized_error = false;
        /* A program that calls for default-initialization [...] of an
      {
        /* Maximum available size in bytes.  Half of the address space
         minus the cookie size.  */
 -      double_int max_size
 -      = double_int_one.llshift (TYPE_PRECISION (sizetype) - 1,
 -                                HOST_BITS_PER_DOUBLE_INT);
 +      offset_int max_size
 +      = wi::set_bit_in_zero <offset_int> (TYPE_PRECISION (sizetype) - 1);
        /* Maximum number of outer elements which can be allocated. */
 -      double_int max_outer_nelts;
 +      offset_int max_outer_nelts;
        tree max_outer_nelts_tree;
  
        gcc_assert (TREE_CODE (size) == INTEGER_CST);
        cookie_size = targetm.cxx.get_cookie_size (elt_type);
        gcc_assert (TREE_CODE (cookie_size) == INTEGER_CST);
 -      gcc_checking_assert (TREE_INT_CST (cookie_size).ult (max_size));
 +      gcc_checking_assert (wi::ltu_p (wi::to_offset (cookie_size), max_size));
        /* Unconditionally subtract the cookie size.  This decreases the
         maximum object size and is safe even if we choose not to use
         a cookie after all.  */
 -      max_size -= TREE_INT_CST (cookie_size);
 +      max_size -= wi::to_offset (cookie_size);
        bool overflow;
 -      inner_size = TREE_INT_CST (size)
 -                 .mul_with_sign (inner_nelts_count, false, &overflow);
 -      if (overflow || inner_size.ugt (max_size))
 +      inner_size = wi::mul (wi::to_offset (size), inner_nelts_count, SIGNED,
 +                          &overflow);
 +      if (overflow || wi::gtu_p (inner_size, max_size))
        {
          if (complain & tf_error)
            error ("size of array is too large");
          return error_mark_node;
        }
 -      max_outer_nelts = max_size.udiv (inner_size, TRUNC_DIV_EXPR);
 +
 +      max_outer_nelts = wi::udiv_trunc (max_size, inner_size);
        /* Only keep the top-most seven bits, to simplify encoding the
         constant in the instruction stream.  */
        {
 -      unsigned shift = HOST_BITS_PER_DOUBLE_INT - 7
 -        - (max_outer_nelts.high ? clz_hwi (max_outer_nelts.high)
 -           : (HOST_BITS_PER_WIDE_INT + clz_hwi (max_outer_nelts.low)));
 -      max_outer_nelts
 -        = max_outer_nelts.lrshift (shift, HOST_BITS_PER_DOUBLE_INT)
 -          .llshift (shift, HOST_BITS_PER_DOUBLE_INT);
 +      unsigned shift = (max_outer_nelts.get_precision ()) - 7
 +        - wi::clz (max_outer_nelts);
 +      max_outer_nelts = wi::lshift (wi::lrshift (max_outer_nelts, shift),
 +                                    shift);
        }
 -      max_outer_nelts_tree = double_int_to_tree (sizetype, max_outer_nelts);
 +      max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);
  
        size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
        outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node,
              cookie_size = NULL_TREE;
              /* No size arithmetic necessary, so the size check is
                 not needed. */
 -            if (outer_nelts_check != NULL && inner_size.is_one ())
 +            if (outer_nelts_check != NULL && inner_size == 1)
                outer_nelts_check = NULL_TREE;
            }
          /* Perform the overflow check.  */
              cookie_size = NULL_TREE;
              /* No size arithmetic necessary, so the size check is
                 not needed. */
 -            if (outer_nelts_check != NULL && inner_size.is_one ())
 +            if (outer_nelts_check != NULL && inner_size == 1)
                outer_nelts_check = NULL_TREE;
            }
  
@@@ -3150,8 -3153,21 +3151,21 @@@ build_vec_delete_1 (tree base, tree max
  
    size_exp = size_in_bytes (type);
  
-   if (! MAYBE_CLASS_TYPE_P (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+   if (! MAYBE_CLASS_TYPE_P (type))
      goto no_destructor;
+   else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+     {
+       /* Make sure the destructor is callable.  */
+       if (type_build_dtor_call (type))
+       {
+         tmp = build_delete (ptype, base, sfk_complete_destructor,
+                             LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1,
+                             complain);
+         if (tmp == error_mark_node)
+           return error_mark_node;
+       }
+       goto no_destructor;
+     }
  
    /* The below is short by the cookie size.  */
    virtual_size = size_binop (MULT_EXPR, size_exp,
@@@ -3637,9 -3653,9 +3651,9 @@@ build_vec_init (tree base, tree maxinde
  
    if (from_array
        || ((type_build_ctor_call (type) || init || explicit_value_init_p)
 -        && ! (host_integerp (maxindex, 0)
 +        && ! (tree_fits_shwi_p (maxindex)
                && (num_initialized_elts
 -                  == tree_low_cst (maxindex, 0) + 1))))
 +                  == tree_to_shwi (maxindex) + 1))))
      {
        /* If the ITERATOR is equal to -1, then we don't have to loop;
         we've already initialized all the elements.  */
        finish_for_init_stmt (for_stmt);
        finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator,
                               build_int_cst (TREE_TYPE (iterator), -1)),
-                      for_stmt);
+                      for_stmt, false);
        elt_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
                                    complain);
        if (elt_init == error_mark_node)
@@@ -3827,7 -3843,7 +3841,7 @@@ build_dtor_call (tree exp, special_func
     flags.  See cp-tree.h for more info.  */
  
  tree
- build_delete (tree type, tree addr, special_function_kind auto_delete,
+ build_delete (tree otype, tree addr, special_function_kind auto_delete,
              int flags, int use_global_delete, tsubst_flags_t complain)
  {
    tree expr;
    if (addr == error_mark_node)
      return error_mark_node;
  
+   tree type = TYPE_MAIN_VARIANT (otype);
    /* Can happen when CURRENT_EXCEPTION_OBJECT gets its type
       set to `error_mark_node' before it gets properly cleaned up.  */
    if (type == error_mark_node)
      return error_mark_node;
  
-   type = TYPE_MAIN_VARIANT (type);
+   if (TREE_CODE (type) == POINTER_TYPE)
+     type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
  
-   addr = mark_rvalue_use (addr);
+   if (TREE_CODE (type) == ARRAY_TYPE)
+     {
+       if (TYPE_DOMAIN (type) == NULL_TREE)
+       {
+         if (complain & tf_error)
+           error ("unknown array size in delete");
+         return error_mark_node;
+       }
+       return build_vec_delete (addr, array_type_nelts (type),
+                              auto_delete, use_global_delete, complain);
+     }
  
-   if (TYPE_PTR_P (type))
+   if (TYPE_PTR_P (otype))
      {
        bool complete_p = true;
  
-       type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-       if (TREE_CODE (type) == ARRAY_TYPE)
-       goto handle_array;
+       addr = mark_rvalue_use (addr);
  
        /* We don't want to warn about delete of void*, only other
          incomplete types.  Deleting other incomplete types
        /* Throw away const and volatile on target type of addr.  */
        addr = convert_force (build_pointer_type (type), addr, 0, complain);
      }
-   else if (TREE_CODE (type) == ARRAY_TYPE)
-     {
-     handle_array:
-       if (TYPE_DOMAIN (type) == NULL_TREE)
-       {
-         if (complain & tf_error)
-           error ("unknown array size in delete");
-         return error_mark_node;
-       }
-       return build_vec_delete (addr, array_type_nelts (type),
-                              auto_delete, use_global_delete, complain);
-     }
    else
      {
        /* Don't check PROTECT here; leave that decision to the
        addr = convert_force (build_pointer_type (type), addr, 0, complain);
      }
  
-   gcc_assert (MAYBE_CLASS_TYPE_P (type));
    if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
      {
+       /* Make sure the destructor is callable.  */
+       if (type_build_dtor_call (type))
+       {
+         expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL,
+                                                        complain),
+                                 sfk_complete_destructor, flags, complain);
+         if (expr == error_mark_node)
+           return error_mark_node;
+       }
        if (auto_delete != sfk_deleting_destructor)
        return void_zero_node;
  
@@@ -4060,7 -4082,7 +4080,7 @@@ push_base_cleanups (void
        for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
           vec_safe_iterate (vbases, i, &base_binfo); i++)
        {
-         if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+         if (type_build_dtor_call (BINFO_TYPE (base_binfo)))
            {
              expr = build_special_member_call (current_class_ref,
                                                base_dtor_identifier,
                                                base_binfo,
                                                (LOOKUP_NORMAL
                                                 | LOOKUP_NONVIRTUAL),
-                                                 tf_warning_or_error);
-             expr = build3 (COND_EXPR, void_type_node, cond,
-                            expr, void_zero_node);
-             finish_decl_cleanup (NULL_TREE, expr);
+                                               tf_warning_or_error);
+             if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+               {
+                 expr = build3 (COND_EXPR, void_type_node, cond,
+                                expr, void_zero_node);
+                 finish_decl_cleanup (NULL_TREE, expr);
+               }
            }
        }
      }
    for (binfo = TYPE_BINFO (current_class_type), i = 0;
         BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
      {
-       if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
-         || BINFO_VIRTUAL_P (base_binfo))
+       if (BINFO_VIRTUAL_P (base_binfo)
+         || !type_build_dtor_call (BINFO_TYPE (base_binfo)))
        continue;
  
        expr = build_special_member_call (current_class_ref,
                                        NULL, base_binfo,
                                        LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                          tf_warning_or_error);
-       finish_decl_cleanup (NULL_TREE, expr);
+       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+       finish_decl_cleanup (NULL_TREE, expr);
      }
  
    /* Don't automatically destroy union members.  */
          || TREE_CODE (member) != FIELD_DECL
          || DECL_ARTIFICIAL (member))
        continue;
-       if (ANON_UNION_TYPE_P (this_type))
+       if (ANON_AGGR_TYPE_P (this_type))
        continue;
-       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
+       if (type_build_dtor_call (this_type))
        {
          tree this_member = (build_class_member_access_expr
                              (current_class_ref, member,
                               sfk_complete_destructor,
                               LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
                               0, tf_warning_or_error);
-         finish_decl_cleanup (NULL_TREE, expr);
+         if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
+           finish_decl_cleanup (NULL_TREE, expr);
        }
      }
  }
diff --combined gcc/cp/method.c
index adef81c576e917d6c59df99e30716fad3665f492,353e99a6410ffc6408d2b916ebc61fac414ca382..fa3f083542b6d0996630e1a6c930cbab9001c838
@@@ -95,7 -95,7 +95,7 @@@ make_thunk (tree function, bool this_ad
                    convert (ssizetype,
                             TYPE_SIZE_UNIT (vtable_entry_type)));
  
 -  d = tree_low_cst (fixed_offset, 0);
 +  d = tree_to_shwi (fixed_offset);
  
    /* See if we already have the thunk in question.  For this_adjusting
       thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it
@@@ -323,7 -323,7 +323,7 @@@ use_thunk (tree thunk_fndecl, bool emit
      {
        if (!this_adjusting)
        virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
 -      virtual_value = tree_low_cst (virtual_offset, /*pos=*/0);
 +      virtual_value = tree_to_shwi (virtual_offset);
        gcc_assert (virtual_value);
      }
    else
                                 this_adjusting, fixed_offset, virtual_value,
                                 virtual_offset, alias);
    if (DECL_ONE_ONLY (function))
-     symtab_add_to_same_comdat_group ((symtab_node) thunk_node,
-                                    (symtab_node) funcn);
+     symtab_add_to_same_comdat_group (thunk_node,
+                                    funcn);
  
    if (!this_adjusting
        || !targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
@@@ -1265,8 -1265,9 +1265,9 @@@ synthesized_method_walk (tree ctype, sp
       class versions and other properties of the type.  But a subobject
       class can be trivially copyable and yet have overload resolution
       choose a template constructor for initialization, depending on
-      rvalueness and cv-quals.  So we can't exit early for copy/move
-      methods in C++0x.  The same considerations apply in C++98/03, but
+      rvalueness and cv-quals.  And furthermore, a member in a base might
+      be trivial but deleted or otherwise not callable.  So we can't exit
+      early in C++0x.  The same considerations apply in C++98/03, but
       there the definition of triviality does not consider overload
       resolution, so a constructor can be trivial even if it would otherwise
       call a non-trivial constructor.  */
            inform (input_location, "defaulted default constructor does "
                    "not initialize any non-static data member");
        }
-       if (!diag)
+       if (!diag && cxx_dialect < cxx11)
        return;
      }
  
  
        process_subob_fn (rval, spec_p, trivial_p, deleted_p,
                        constexpr_p, diag, basetype);
-       if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype))
+       if (ctor_p)
        {
          /* In a constructor we also need to check the subobject
             destructors for cleanup of partially constructed objects.  */
@@@ -1465,13 -1466,34 +1466,34 @@@ maybe_explain_implicit_delete (tree dec
          tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl);
          tree parm_type = TREE_VALUE (parms);
          bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
+         tree raises = NULL_TREE;
+         bool deleted_p = false;
          tree scope = push_scope (ctype);
-         inform (0, "%q+#D is implicitly deleted because the default "
-                "definition would be ill-formed:", decl);
-         pop_scope (scope);
          synthesized_method_walk (ctype, sfk, const_p,
-                                  NULL, NULL, NULL, NULL, true,
+                                  &raises, NULL, &deleted_p, NULL, false,
                                   DECL_INHERITED_CTOR_BASE (decl), parms);
+         if (deleted_p)
+           {
+             inform (0, "%q+#D is implicitly deleted because the default "
+                     "definition would be ill-formed:", decl);
+             synthesized_method_walk (ctype, sfk, const_p,
+                                      NULL, NULL, NULL, NULL, true,
+                                      DECL_INHERITED_CTOR_BASE (decl), parms);
+           }
+         else if (!comp_except_specs
+                  (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)),
+                   raises, ce_normal))
+           inform (DECL_SOURCE_LOCATION (decl), "%q#F is implicitly "
+                   "deleted because its exception-specification does not "
+                   "match the implicit exception-specification %qX",
+                   decl, raises);
+ #ifdef ENABLE_CHECKING
+         else
+           gcc_unreachable ();
+ #endif
+         pop_scope (scope);
        }
  
        input_location = loc;
@@@ -1781,9 -1803,10 +1803,10 @@@ defaulted_late_check (tree fn
                              eh_spec, ce_normal))
        {
          if (DECL_DEFAULTED_IN_CLASS_P (fn))
-           error ("function %q+D defaulted on its first declaration "
-                  "with an exception-specification that differs from "
-                  "the implicit declaration %q#D", fn, implicit_fn);
+           {
+             DECL_DELETED_FN (fn) = true;
+             eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
+           }
          else
            error ("function %q+D defaulted on its redeclaration "
                   "with an exception-specification that differs from "
diff --combined gcc/cp/parser.c
index 383ea46b7b5e506b04fd2832f4c873bba9cbfd8d,3df746a3683fbe799d9c54b950eef874eb3c008b..06d779698f4d5fc8281dc47cbff088d4ae7eb680
@@@ -819,7 -819,7 +819,7 @@@ cp_lexer_get_preprocessor_token (cp_lex
      {
        /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
        token->pragma_kind = ((enum pragma_kind)
 -                          TREE_INT_CST_LOW (token->u.value));
 +                          tree_to_hwi (token->u.value));
        token->u.value = NULL_TREE;
      }
  }
@@@ -1970,15 -1970,15 +1970,15 @@@ static tree cp_parser_selection_stateme
  static tree cp_parser_condition
    (cp_parser *);
  static tree cp_parser_iteration_statement
-   (cp_parser *);
+   (cp_parser *, bool);
  static bool cp_parser_for_init_statement
    (cp_parser *, tree *decl);
  static tree cp_parser_for
-   (cp_parser *);
+   (cp_parser *, bool);
  static tree cp_parser_c_for
-   (cp_parser *, tree, tree);
+   (cp_parser *, tree, tree, bool);
  static tree cp_parser_range_for
-   (cp_parser *, tree, tree, tree);
+   (cp_parser *, tree, tree, tree, bool);
  static void do_range_for_auto_deduction
    (tree, tree);
  static tree cp_parser_perform_range_for_lookup
@@@ -3793,22 -3793,39 +3793,39 @@@ 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);
-   for (i = 0; i < len; ++i)
-     TREE_VEC_ELT (charvec, i) = build_int_cst (string_char_type_node, str[i]);
+   if (sz == 1)
+     {
+       for (int i = 0; i < len; ++i)
+       TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, str[i]);
+     }
+   else if (sz == 2)
+     {
+       const uint16_t *num = (const uint16_t *)str;
+       for (int i = 0; i < len; ++i)
+       TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, num[i]);
+     }
+   else if (sz == 4)
+     {
+       const uint32_t *num = (const uint32_t *)str;
+       for (int i = 0; i < len; ++i)
+       TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, num[i]);
+     }
  
    /* Build the argument packs.  */
    SET_ARGUMENT_PACK_ARGS (argpack, charvec);
-   TREE_TYPE (argpack) = string_char_type_node;
+   TREE_TYPE (argpack) = str_char_type_node;
  
    TREE_VEC_ELT (argvec, 1) = argpack;
  
@@@ -3912,7 -3929,7 +3929,7 @@@ cp_parser_userdef_string_literal (cp_to
    tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
    tree value = USERDEF_LITERAL_VALUE (literal);
    int len = TREE_STRING_LENGTH (value)
 -      / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1;
 +      / tree_to_hwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1;
    tree decl, result;
    vec<tree, va_gc> *args;
  
@@@ -5800,31 -5817,45 +5817,45 @@@ cp_parser_postfix_expression (cp_parse
            && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
          {
            tree initializer = NULL_TREE;
-           bool saved_in_type_id_in_expr_p;
+           bool compound_literal_p;
  
            cp_parser_parse_tentatively (parser);
            /* Consume the `('.  */
            cp_lexer_consume_token (parser->lexer);
-           /* Parse the type.  */
-           saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
-           parser->in_type_id_in_expr_p = true;
-           type = cp_parser_type_id (parser);
-           parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
-           /* Look for the `)'.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+           /* Avoid calling cp_parser_type_id pointlessly, see comment
+              in cp_parser_cast_expression about c++/29234.  */
+           cp_lexer_save_tokens (parser->lexer);
+           compound_literal_p
+             = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
+                                                       /*consume_paren=*/true)
+                && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE));
+           /* Roll back the tokens we skipped.  */
+           cp_lexer_rollback_tokens (parser->lexer);
+           if (!compound_literal_p)
+             cp_parser_simulate_error (parser);
+           else
+             {
+               /* Parse the type.  */
+               bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+               parser->in_type_id_in_expr_p = true;
+               type = cp_parser_type_id (parser);
+               parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
+               /* Look for the `)'.  */
+               cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+             }
            /* If things aren't going well, there's no need to
               keep going.  */
            if (!cp_parser_error_occurred (parser))
              {
-               if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
-                 {
-                   bool non_constant_p;
-                   /* Parse the brace-enclosed initializer list.  */
-                   initializer = cp_parser_braced_list (parser,
-                                                        &non_constant_p);
-                 }
-               else
-                 cp_parser_simulate_error (parser);
+               bool non_constant_p;
+               /* Parse the brace-enclosed initializer list.  */
+               initializer = cp_parser_braced_list (parser,
+                                                    &non_constant_p);
              }
            /* If that worked, we're definitely looking at a
               compound-literal expression.  */
@@@ -7492,6 -7523,7 +7523,7 @@@ cp_parser_tokens_start_cast_expression 
      case CPP_CLOSE_SQUARE:
      case CPP_CLOSE_PAREN:
      case CPP_CLOSE_BRACE:
+     case CPP_OPEN_BRACE:
      case CPP_DOT:
      case CPP_DOT_STAR:
      case CPP_DEREF:
@@@ -7559,7 -7591,7 +7591,7 @@@ cp_parser_cast_expression (cp_parser *p
      {
        tree type = NULL_TREE;
        tree expr = NULL_TREE;
-       bool compound_literal_p;
+       bool cast_expression_p;
        const char *saved_message;
  
        /* There's no way to know yet whether or not this is a cast.
         will commit to the parse at that point, because we cannot
         undo the action that is done when creating a new class.  So,
         then we cannot back up and do a postfix-expression.
+        Another tricky case is the following (c++/29234):
+          struct S { void operator () (); };
+          void foo ()
+          {
+            ( S()() );
+          }
+        As a type-id we parse the parenthesized S()() as a function
+        returning a function, groktypename complains and we cannot
+        back up in this case either.
  
         Therefore, we scan ahead to the closing `)', and check to see
-        if the token after the `)' is a `{'.  If so, we are not
-        looking at a cast-expression.
+        if the tokens after the `)' can start a cast-expression.  Otherwise
+        we are dealing with an unary-expression, a postfix-expression
+        or something else.
  
         Save tokens so that we can put them back.  */
        cp_lexer_save_tokens (parser->lexer);
-       /* Skip tokens until the next token is a closing parenthesis.
-        If we find the closing `)', and the next token is a `{', then
-        we are looking at a compound-literal.  */
-       compound_literal_p
+       /* We may be looking at a cast-expression.  */
+       cast_expression_p
        = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
                                                  /*consume_paren=*/true)
-          && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE));
+          && cp_parser_tokens_start_cast_expression (parser));
        /* Roll back the tokens we skipped.  */
        cp_lexer_rollback_tokens (parser->lexer);
-       /* If we were looking at a compound-literal, simulate an error
-        so that the call to cp_parser_parse_definitely below will
-        fail.  */
-       if (compound_literal_p)
+       /* If we aren't looking at a cast-expression, simulate an error so
+        that the call to cp_parser_parse_definitely below will fail.  */
+       if (!cast_expression_p)
        cp_parser_simulate_error (parser);
        else
        {
        /* At this point this can only be either a cast or a
         parenthesized ctor such as `(T ())' that looks like a cast to
         function returning T.  */
-       if (!cp_parser_error_occurred (parser)
-         && cp_parser_tokens_start_cast_expression (parser))
+       if (!cp_parser_error_occurred (parser))
        {
          cp_parser_parse_definitely (parser);
          expr = cp_parser_cast_expression (parser,
@@@ -9231,7 -9274,7 +9274,7 @@@ cp_parser_statement (cp_parser* parser
        case RID_WHILE:
        case RID_DO:
        case RID_FOR:
-         statement = cp_parser_iteration_statement (parser);
+         statement = cp_parser_iteration_statement (parser, false);
          break;
  
        case RID_BREAK:
@@@ -9892,7 -9935,7 +9935,7 @@@ cp_parser_condition (cp_parser* parser
     not included. */
  
  static tree
- cp_parser_for (cp_parser *parser)
+ cp_parser_for (cp_parser *parser, bool ivdep)
  {
    tree init, scope, decl;
    bool is_range_for;
    is_range_for = cp_parser_for_init_statement (parser, &decl);
  
    if (is_range_for)
-     return cp_parser_range_for (parser, scope, init, decl);
+     return cp_parser_range_for (parser, scope, init, decl, ivdep);
    else
-     return cp_parser_c_for (parser, scope, init);
+     return cp_parser_c_for (parser, scope, init, ivdep);
  }
  
  static tree
- cp_parser_c_for (cp_parser *parser, tree scope, tree init)
+ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep)
  {
    /* Normal for loop */
    tree condition = NULL_TREE;
    /* If there's a condition, process it.  */
    if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
      condition = cp_parser_condition (parser);
-   finish_for_cond (condition, stmt);
+   else if (ivdep)
+     {
+       cp_parser_error (parser, "missing loop condition in loop with "
+                      "%<GCC ivdep%> pragma");
+       condition = error_mark_node;
+     }
+   finish_for_cond (condition, stmt, ivdep);
    /* Look for the `;'.  */
    cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
  
    regular FOR_STMT.  */
  
  static tree
- cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
+ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
+                    bool ivdep)
  {
    tree stmt, range_expr;
  
        if (check_for_bare_parameter_packs (range_expr))
        range_expr = error_mark_node;
        stmt = begin_range_for_stmt (scope, init);
+       if (ivdep)
+       RANGE_FOR_IVDEP (stmt) = 1;
        finish_range_for_decl (stmt, range_decl, range_expr);
        if (!type_dependent_expression_p (range_expr)
          /* do_auto_deduction doesn't mess with template init-lists.  */
    else
      {
        stmt = begin_for_stmt (scope, init);
-       stmt = cp_convert_range_for (stmt, range_decl, range_expr);
+       stmt = cp_convert_range_for (stmt, range_decl, range_expr, ivdep);
      }
    return stmt;
  }
@@@ -10067,7 -10119,8 +10119,8 @@@ do_range_for_auto_deduction (tree decl
     namespace.  */
  
  tree
- cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
+ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
+                     bool ivdep)
  {
    tree begin, end;
    tree iter_type, begin_expr, end_expr;
                                 begin, ERROR_MARK,
                                 end, ERROR_MARK,
                                 NULL, tf_warning_or_error);
-   finish_for_cond (condition, statement);
+   finish_for_cond (condition, statement, ivdep);
  
    /* The new increment expression.  */
    expression = finish_unary_op_expr (input_location,
@@@ -10287,7 -10340,7 +10340,7 @@@ cp_parser_range_for_member_function (tr
     Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT.  */
  
  static tree
- cp_parser_iteration_statement (cp_parser* parser)
+ cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
  {
    cp_token *token;
    enum rid keyword;
        cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
-       finish_while_stmt_cond (condition, statement);
+       finish_while_stmt_cond (condition, statement, ivdep);
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
        /* Parse the dependent statement.  */
        /* Parse the expression.  */
        expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
        /* We're done with the do-statement.  */
-       finish_do_stmt (expression, statement);
+       finish_do_stmt (expression, statement, ivdep);
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
        /* Look for the `;'.  */
        /* Look for the `('.  */
        cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
  
-       statement = cp_parser_for (parser);
+       statement = cp_parser_for (parser, ivdep);
  
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
@@@ -21426,6 -21479,9 +21479,9 @@@ cp_parser_std_attribute (cp_parser *par
        /* C++11 noreturn attribute is equivalent to GNU's.  */
        if (is_attribute_p ("noreturn", attr_id))
        TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
+       /* C++14 deprecated attribute is equivalent to GNU's.  */
+       else if (cxx_dialect >= cxx1y && is_attribute_p ("deprecated", attr_id))
+       TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
      }
  
    /* Now parse the optional argument clause of the attribute.  */
@@@ -22155,6 -22211,7 +22211,7 @@@ static boo
  cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
  {
    bool constructor_p;
+   bool outside_class_specifier_p;
    tree nested_name_specifier;
    cp_token *next_token;
  
                                            /*check_dependency_p=*/false,
                                            /*type_p=*/false,
                                            /*is_declaration=*/false));
+   outside_class_specifier_p = (!at_class_scope_p ()
+                              || !TYPE_BEING_DEFINED (current_class_type)
+                              || friend_p);
    /* Outside of a class-specifier, there must be a
       nested-name-specifier.  */
-   if (!nested_name_specifier &&
-       (!at_class_scope_p () || !TYPE_BEING_DEFINED (current_class_type)
-        || friend_p))
+   if (!nested_name_specifier && outside_class_specifier_p)
      constructor_p = false;
    else if (nested_name_specifier == error_mark_node)
      constructor_p = false;
                                        /*check_dependency_p=*/false,
                                        /*class_head_p=*/false,
                                        /*is_declaration=*/false);
-       /* If there was no class-name, then this is not a constructor.  */
-       constructor_p = !cp_parser_error_occurred (parser);
+       /* If there was no class-name, then this is not a constructor.
+        Otherwise, if we are in a class-specifier and we aren't
+        handling a friend declaration, check that its type matches
+        current_class_type (c++/38313).  Note: error_mark_node
+        is left alone for error recovery purposes.  */
+       constructor_p = (!cp_parser_error_occurred (parser)
+                      && (outside_class_specifier_p
+                          || type_decl == error_mark_node
+                          || same_type_p (current_class_type,
+                                          TREE_TYPE (type_decl))));
  
        /* If we're still considering a constructor, we have to see a `(',
         to begin the parameter-declaration-clause, followed by either a
@@@ -23199,6 -23267,9 +23267,9 @@@ cp_parser_late_parse_one_default_arg (c
              && CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg))
            flags = LOOKUP_NORMAL;
          parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags);
+         if (TREE_CODE (parsed_arg) == TARGET_EXPR)
+           /* This represents the whole initialization.  */
+           TARGET_EXPR_DIRECT_INIT_P (parsed_arg) = true;
        }
      }
  
@@@ -26796,8 -26867,8 +26867,8 @@@ cp_parser_omp_clause_collapse (cp_parse
      return list;
    num = fold_non_dependent_expr (num);
    if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
 -      || !host_integerp (num, 0)
 -      || (n = tree_low_cst (num, 0)) <= 0
 +      || !tree_fits_shwi_p (num)
 +      || (n = tree_to_shwi (num)) <= 0
        || (int) n != n)
      {
        error_at (loc, "collapse argument needs positive constant integer expression");
@@@ -28579,7 -28650,7 +28650,7 @@@ cp_parser_omp_for_loop (cp_parser *pars
  
    for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
      if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
 -      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
 +      collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
  
    gcc_assert (collapse >= 1);
  
@@@ -30906,6 -30977,22 +30977,22 @@@ cp_parser_pragma (cp_parser *parser, en
                "%<#pragma omp sections%> construct");
        break;
  
+     case PRAGMA_IVDEP:
+       {
+       cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+       cp_token *tok;
+       tok = cp_lexer_peek_token (the_parser->lexer);
+       if (tok->type != CPP_KEYWORD
+           || (tok->keyword != RID_FOR && tok->keyword != RID_WHILE
+               && tok->keyword != RID_DO))
+         {
+           cp_parser_error (parser, "for, while or do statement expected");
+           return false;
+         }
+       cp_parser_iteration_statement (parser, true);
+       return true;
+       }
      default:
        gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
        c_invoke_pragma_handler (id);
diff --combined gcc/cp/semantics.c
index b30794c183e57f5561d720576ff608825f0cfbc3,366756fd437593eae7e886b343e1456064dac8cb..2ebc00d243a05f3d00e2c79b9a90080574709c6c
@@@ -726,9 -726,15 +726,15 @@@ begin_while_stmt (void
     WHILE_STMT.  */
  
  void
- finish_while_stmt_cond (tree cond, tree while_stmt)
+ finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep)
  {
    finish_cond (&WHILE_COND (while_stmt), maybe_convert_cond (cond));
+   if (ivdep && cond != error_mark_node)
+     WHILE_COND (while_stmt) = build2 (ANNOTATE_EXPR,
+                                     TREE_TYPE (WHILE_COND (while_stmt)),
+                                     WHILE_COND (while_stmt),
+                                     build_int_cst (integer_type_node,
+                                                    annot_expr_ivdep_kind));
    simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt));
  }
  
@@@ -771,9 -777,12 +777,12 @@@ finish_do_body (tree do_stmt
     COND is as indicated.  */
  
  void
- finish_do_stmt (tree cond, tree do_stmt)
+ finish_do_stmt (tree cond, tree do_stmt, bool ivdep)
  {
    cond = maybe_convert_cond (cond);
+   if (ivdep && cond != error_mark_node)
+     cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+                  build_int_cst (integer_type_node, annot_expr_ivdep_kind));
    DO_COND (do_stmt) = cond;
  }
  
@@@ -876,9 -885,15 +885,15 @@@ finish_for_init_stmt (tree for_stmt
     FOR_STMT.  */
  
  void
- finish_for_cond (tree cond, tree for_stmt)
+ finish_for_cond (tree cond, tree for_stmt, bool ivdep)
  {
    finish_cond (&FOR_COND (for_stmt), maybe_convert_cond (cond));
+   if (ivdep && cond != error_mark_node)
+     FOR_COND (for_stmt) = build2 (ANNOTATE_EXPR,
+                                 TREE_TYPE (FOR_COND (for_stmt)),
+                                 FOR_COND (for_stmt),
+                                 build_int_cst (integer_type_node,
+                                                annot_expr_ivdep_kind));
    simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt));
  }
  
@@@ -2501,6 -2516,7 +2516,7 @@@ finish_compound_literal (tree type, tre
    if ((!at_function_scope_p () || CP_TYPE_CONST_P (type))
        && TREE_CODE (type) == ARRAY_TYPE
        && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+       && !cp_unevaluated_operand
        && initializer_constant_valid_p (compound_literal, type))
      {
        tree decl = create_temporary_var (type);
        decl = pushdecl_top_level (decl);
        DECL_NAME (decl) = make_anon_name ();
        SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
+       /* Make sure the destructor is callable.  */
+       tree clean = cxx_maybe_build_cleanup (decl, complain);
+       if (clean == error_mark_node)
+       return error_mark_node;
        return decl;
      }
    else
@@@ -5168,12 -5188,16 +5188,16 @@@ finish_omp_clauses (tree clauses
          if (t == NULL_TREE)
            t = integer_one_node;
          if (t == error_mark_node)
-           remove = true;
+           {
+             remove = true;
+             break;
+           }
          else if (!type_dependent_expression_p (t)
                   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
              error ("linear step expression must be integral");
              remove = true;
+             break;
            }
          else
            {
                                           MINUS_EXPR, sizetype, t,
                                           OMP_CLAUSE_DECL (c));
                      if (t == error_mark_node)
-                       remove = true;
+                       {
+                         remove = true;
+                         break;
+                       }
                    }
                }
              OMP_CLAUSE_LINEAR_STEP (c) = t;
                error ("%qE is not a variable in %<aligned%> clause", t);
              remove = true;
            }
+         else if (!type_dependent_expression_p (t)
+                  && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
+                  && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE
+                  && (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
+                      || (!POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (t)))
+                          && (TREE_CODE (TREE_TYPE (TREE_TYPE (t)))
+                              != ARRAY_TYPE))))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE in %<aligned%> clause is neither a pointer nor "
+                       "an array nor a reference to pointer or array", t);
+             remove = true;
+           }
          else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
            {
              error ("%qD appears more than once in %<aligned%> clauses", t);
              else
                error ("%qE is not an argument in %<uniform%> clause", t);
              remove = true;
+             break;
            }
-         break;
+         goto check_dup_generic;
  
        case OMP_CLAUSE_NOWAIT:
        case OMP_CLAUSE_ORDERED:
@@@ -7398,8 -7439,7 +7439,7 @@@ build_anon_member_initialization (tree 
       to build up the initializer from the outside in so that we can reuse
       previously built CONSTRUCTORs if this is, say, the second field in an
       anonymous struct.  So we use a vec as a stack.  */
-   vec<tree> fields;
-   fields.create (2);
+   stack_vec<tree, 2> fields;
    do
      {
        fields.safe_push (TREE_OPERAND (member, 1));
    /* Now we're at the innermost field, the one that isn't an anonymous
       aggregate.  Add its initializer to the CONSTRUCTOR and we're done.  */
    gcc_assert (fields.is_empty());
-   fields.release ();
    CONSTRUCTOR_APPEND_ELT (*vec, field, init);
  
    return true;
@@@ -8269,12 -8308,18 +8308,18 @@@ cxx_eval_call_expression (const constex
        return t;
      }
  
-   /* Shortcut trivial copy constructor/op=.  */
-   if (call_expr_nargs (t) == 2 && trivial_fn_p (fun))
+   /* Shortcut trivial constructor/op=.  */
+   if (trivial_fn_p (fun))
      {
-       tree arg = convert_from_reference (get_nth_callarg (t, 1));
-       return cxx_eval_constant_expression (old_call, arg, allow_non_constant,
-                                          addr, non_constant_p, overflow_p);
+       if (call_expr_nargs (t) == 2)
+       {
+         tree arg = convert_from_reference (get_nth_callarg (t, 1));
+         return cxx_eval_constant_expression (old_call, arg, allow_non_constant,
+                                              addr, non_constant_p, overflow_p);
+       }
+       else if (TREE_CODE (t) == AGGR_INIT_EXPR
+              && AGGR_INIT_ZERO_FIRST (t))
+       return build_zero_init (DECL_CONTEXT (fun), NULL_TREE, false);
      }
  
    /* If in direct recursive call, optimize definition search.  */
@@@ -8560,7 -8605,7 +8605,7 @@@ cxx_eval_array_reference (const constex
        *non_constant_p = true;
        return t;
      }
 -  i = tree_low_cst (index, 0);
 +  i = tree_to_shwi (index);
    if (TREE_CODE (ary) == CONSTRUCTOR)
      return (*CONSTRUCTOR_ELTS (ary))[i].value;
    else if (elem_nchars == 1)
@@@ -8675,8 -8720,8 +8720,8 @@@ cxx_eval_bit_field_ref (const constexpr
                         TREE_OPERAND (t, 1), TREE_OPERAND (t, 2));
  
    start = TREE_OPERAND (t, 2);
 -  istart = tree_low_cst (start, 0);
 -  isize = tree_low_cst (TREE_OPERAND (t, 1), 0);
 +  istart = tree_to_shwi (start);
 +  isize = tree_to_shwi (TREE_OPERAND (t, 1));
    utype = TREE_TYPE (t);
    if (!TYPE_UNSIGNED (utype))
      utype = build_nonstandard_integer_type (TYPE_PRECISION (utype), 1);
        return value;
        if (TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE
          && TREE_CODE (value) == INTEGER_CST
 -        && host_integerp (bitpos, 0)
 -        && host_integerp (DECL_SIZE (field), 0))
 +        && tree_fits_shwi_p (bitpos)
 +        && tree_fits_shwi_p (DECL_SIZE (field)))
        {
 -        HOST_WIDE_INT bit = tree_low_cst (bitpos, 0);
 -        HOST_WIDE_INT sz = tree_low_cst (DECL_SIZE (field), 0);
 +        HOST_WIDE_INT bit = tree_to_shwi (bitpos);
 +        HOST_WIDE_INT sz = tree_to_shwi (DECL_SIZE (field));
          HOST_WIDE_INT shift;
          if (bit >= istart && bit + sz <= istart + isize)
            {
@@@ -8849,7 -8894,7 +8894,7 @@@ cxx_eval_vec_init_1 (const constexpr_ca
                     bool *non_constant_p, bool *overflow_p)
  {
    tree elttype = TREE_TYPE (atype);
 -  int max = tree_low_cst (array_type_nelts (atype), 0);
 +  int max = tree_to_shwi (array_type_nelts (atype));
    vec<constructor_elt, va_gc> *n;
    vec_alloc (n, max + 1);
    bool pre_init = false;
@@@ -9068,9 -9113,9 +9113,9 @@@ cxx_fold_indirect_ref (location_t loc, 
              && (same_type_ignoring_top_level_qualifiers_p
                  (type, TREE_TYPE (op00type))))
            {
 -            HOST_WIDE_INT offset = tree_low_cst (op01, 0);
 +            HOST_WIDE_INT offset = tree_to_shwi (op01);
              tree part_width = TYPE_SIZE (type);
 -            unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
 +            unsigned HOST_WIDE_INT part_widthi = tree_to_shwi (part_width)/BITS_PER_UNIT;
              unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
              tree index = bitsize_int (indexi);
  
diff --combined gcc/cp/tree.c
index 273131fccaef2be3b2ad87d0de1027027202dcc5,3ac034806200a06396759fb79b77a4a475a347b7..14b69921a5143a30761177f074e89eecd7f5af1d
@@@ -32,7 -32,6 +32,7 @@@ along with GCC; see the file COPYING3
  #include "splay-tree.h"
  #include "gimple.h" /* gimple_has_body_p */
  #include "hash-table.h"
 +#include "wide-int.h"
  
  static tree bot_manip (tree *, int *, void *);
  static tree bot_replace (tree *, int *, void *);
@@@ -1693,7 -1692,7 +1693,7 @@@ debug_binfo (tree elem
    fprintf (stderr, "type \"%s\", offset = " HOST_WIDE_INT_PRINT_DEC
           "\nvtable type:\n",
           TYPE_NAME_STRING (BINFO_TYPE (elem)),
 -         TREE_INT_CST_LOW (BINFO_OFFSET (elem)));
 +         tree_to_hwi (BINFO_OFFSET (elem)));
    debug_tree (BINFO_TYPE (elem));
    if (BINFO_VTABLE (elem))
      fprintf (stderr, "vtable decl \"%s\"\n",
        tree fndecl = TREE_VALUE (virtuals);
        fprintf (stderr, "%s [%ld =? %ld]\n",
               IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
 -             (long) n, (long) TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
 +             (long) n, (long) tree_to_hwi (DECL_VINDEX (fndecl)));
        ++n;
        virtuals = TREE_CHAIN (virtuals);
      }
@@@ -2602,7 -2601,8 +2602,7 @@@ cp_tree_equal (tree t1, tree t2
    switch (code1)
      {
      case INTEGER_CST:
 -      return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
 -      && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
 +      return wi::to_widest (t1) == wi::to_widest (t2);
  
      case REAL_CST:
        return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
@@@ -3240,7 -3240,7 +3240,7 @@@ handle_init_priority_attribute (tree* n
        return NULL_TREE;
      }
  
 -  pri = TREE_INT_CST_LOW (initp_expr);
 +  pri = tree_to_hwi (initp_expr);
  
    type = strip_array_types (type);
  
@@@ -3983,8 -3983,8 +3983,8 @@@ cp_fix_function_decl_p (tree decl
  
        /* Don't fix same_body aliases.  Although they don't have their own
         CFG, they share it with what they alias to.  */
-       if (!node || !node->symbol.alias
-         || !vec_safe_length (node->symbol.ref_list.references))
+       if (!node || !node->alias
+         || !vec_safe_length (node->ref_list.references))
        return true;
      }
  
diff --combined gcc/cp/typeck2.c
index 3fc046619bc2d1eb64716da9ce203a635595343b,9da8e3de8444f8533470c0c2f6f63ffacad8326c..cb5f715f6506157ad6c9fed3eff3754841a30d95
@@@ -34,7 -34,6 +34,7 @@@ along with GCC; see the file COPYING3
  #include "cp-tree.h"
  #include "flags.h"
  #include "diagnostic-core.h"
 +#include "wide-int.h"
  
  static tree
  process_init_constructor (tree type, tree init, tsubst_flags_t complain);
@@@ -641,12 -640,13 +641,13 @@@ split_nonconstant_init_1 (tree dest, tr
              code = build_stmt (input_location, EXPR_STMT, code);
              code = maybe_cleanup_point_expr_void (code);
              add_stmt (code);
-             if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
+             if (type_build_dtor_call (inner_type))
                {
                  code = (build_special_member_call
                          (sub, complete_dtor_identifier, NULL, inner_type,
                           LOOKUP_NORMAL, tf_warning_or_error));
-                 finish_eh_cleanup (code);
+                 if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
+                   finish_eh_cleanup (code);
                }
  
              num_split_elts++;
@@@ -775,7 -775,6 +776,6 @@@ store_init_value (tree decl, tree init
      {
        bool const_init;
        value = fold_non_dependent_expr (value);
-       value = maybe_constant_init (value);
        if (DECL_DECLARED_CONSTEXPR_P (decl)
          || DECL_IN_AGGR_P (decl))
        {
          else
            value = cxx_constant_value (value);
        }
+       value = maybe_constant_init (value);
        const_init = (reduced_constant_expression_p (value)
                    || error_operand_p (value));
        DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init;
@@@ -834,7 -834,8 +835,8 @@@ check_narrowing (tree type, tree init
        && TREE_CODE (type) == COMPLEX_TYPE)
      {
        tree elttype = TREE_TYPE (type);
-       check_narrowing (elttype, CONSTRUCTOR_ELT (init, 0)->value);
+       if (CONSTRUCTOR_NELTS (init) > 0)
+         check_narrowing (elttype, CONSTRUCTOR_ELT (init, 0)->value);
        if (CONSTRUCTOR_NELTS (init) > 1)
        check_narrowing (elttype, CONSTRUCTOR_ELT (init, 1)->value);
        return;
@@@ -980,7 -981,7 +982,7 @@@ digest_init_r (tree type, tree init, bo
            }
          if (TYPE_DOMAIN (type) != 0 && TREE_CONSTANT (TYPE_SIZE (type)))
            {
 -            int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
 +            int size = tree_to_hwi (TYPE_SIZE (type));
              size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
              /* In C it is ok to subtract 1 from the length of the string
                 because it's ok to ignore the terminating null char that is
@@@ -1119,10 -1120,12 +1121,10 @@@ process_init_constructor_array (tree ty
      {
        tree domain = TYPE_DOMAIN (type);
        if (domain && TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
 -      len = (tree_to_double_int (TYPE_MAX_VALUE (domain))
 -             - tree_to_double_int (TYPE_MIN_VALUE (domain))
 -             + double_int_one)
 -            .ext (TYPE_PRECISION (TREE_TYPE (domain)),
 -                  TYPE_UNSIGNED (TREE_TYPE (domain)))
 -            .low;
 +      len = wi::ext (wi::to_offset (TYPE_MAX_VALUE (domain))
 +                     - wi::to_offset (TYPE_MIN_VALUE (domain)) + 1,
 +                     TYPE_PRECISION (TREE_TYPE (domain)),
 +                     TYPE_SIGN (TREE_TYPE (domain))).to_uhwi ();
        else
        unbounded = true;  /* Take as many as there are.  */
      }
diff --combined gcc/cppbuiltin.c
index 86ef5cbd2ca441b2e257c3e6b5b5f8c9d2700721,cd74e2349c4a97107a3421a7946de54eb56cca8d..0c112654cd5242c806d29634da7d933ebd707e10
@@@ -105,6 -105,8 +105,8 @@@ define_builtin_macros_for_compilation_f
  
    cpp_define_formatted (pfile, "__FINITE_MATH_ONLY__=%d",
                        flag_finite_math_only);
+   if (flag_enable_cilkplus)
+     cpp_define (pfile, "__cilk=200");
  }
  
  
@@@ -128,7 -130,7 +130,7 @@@ define_builtin_macros_for_type_sizes (c
  {
  #define define_type_sizeof(NAME, TYPE)                             \
      cpp_define_formatted (pfile, NAME"="HOST_WIDE_INT_PRINT_DEC,   \
 -                          tree_low_cst (TYPE_SIZE_UNIT (TYPE), 1))
 +                          tree_to_uhwi (TYPE_SIZE_UNIT (TYPE)))
  
    define_type_sizeof ("__SIZEOF_INT__", integer_type_node);
    define_type_sizeof ("__SIZEOF_LONG__", long_integer_type_node);
diff --combined gcc/dbxout.c
index e87e6eebd2f2736c9a6ba2f5305cd7813967a33c,84f765efe5e7bd07b9c1d21a577eb862c0b24a28..d110a9475f60d5f95088925c980ff03a3991c94e
@@@ -690,39 -690,88 +690,39 @@@ stabstr_U (unsigned HOST_WIDE_INT num
  static void
  stabstr_O (tree cst)
  {
 -  unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (cst);
 -  unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
 -
 -  char buf[128];
 -  char *p = buf + sizeof buf;
 -
 -  /* GDB wants constants with no extra leading "1" bits, so
 -     we need to remove any sign-extension that might be
 -     present.  */
 -  {
 -    const unsigned int width = TYPE_PRECISION (TREE_TYPE (cst));
 -    if (width == HOST_BITS_PER_DOUBLE_INT)
 -      ;
 -    else if (width > HOST_BITS_PER_WIDE_INT)
 -      high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);
 -    else if (width == HOST_BITS_PER_WIDE_INT)
 -      high = 0;
 -    else
 -      high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
 -  }
 +  int prec = TYPE_PRECISION (TREE_TYPE (cst));
 +  int res_pres = prec % 3;
 +  int i;
 +  unsigned int digit;
  
    /* Leading zero for base indicator.  */
    stabstr_C ('0');
  
    /* If the value is zero, the base indicator will serve as the value
       all by itself.  */
 -  if (high == 0 && low == 0)
 +  if (wi::eq_p (cst, 0))
      return;
  
 -  /* If the high half is zero, we need only print the low half normally.  */
 -  if (high == 0)
 -    NUMBER_FMT_LOOP (p, low, 8);
 -  else
 +  /* GDB wants constants with no extra leading "1" bits, so
 +     we need to remove any sign-extension that might be
 +     present.  */
 +  if (res_pres == 1)
      {
 -      /* When high != 0, we need to print enough zeroes from low to
 -       give the digits from high their proper place-values.  Hence
 -       NUMBER_FMT_LOOP cannot be used.  */
 -      const int n_digits = HOST_BITS_PER_WIDE_INT / 3;
 -      int i;
 -
 -      for (i = 1; i <= n_digits; i++)
 -      {
 -        unsigned int digit = low % 8;
 -        low /= 8;
 -        *--p = '0' + digit;
 -      }
 -
 -      /* Octal digits carry exactly three bits of information.  The
 -       width of a HOST_WIDE_INT is not normally a multiple of three.
 -       Therefore, the next digit printed probably needs to carry
 -       information from both low and high.  */
 -      if (HOST_BITS_PER_WIDE_INT % 3 != 0)
 -      {
 -        const int n_leftover_bits = HOST_BITS_PER_WIDE_INT % 3;
 -        const int n_bits_from_high = 3 - n_leftover_bits;
 -
 -        const unsigned HOST_WIDE_INT
 -          low_mask = (((unsigned HOST_WIDE_INT)1) << n_leftover_bits) - 1;
 -        const unsigned HOST_WIDE_INT
 -          high_mask = (((unsigned HOST_WIDE_INT)1) << n_bits_from_high) - 1;
 -
 -        unsigned int digit;
 -
 -        /* At this point, only the bottom n_leftover_bits bits of low
 -           should be set.  */
 -        gcc_assert (!(low & ~low_mask));
 -
 -        digit = (low | ((high & high_mask) << n_leftover_bits));
 -        high >>= n_bits_from_high;
 -
 -        *--p = '0' + digit;
 -      }
 -
 -      /* Now we can format high in the normal manner.  However, if
 -       the only bits of high that were set were handled by the
 -       digit split between low and high, high will now be zero, and
 -       we don't want to print extra digits in that case.  */
 -      if (high)
 -      NUMBER_FMT_LOOP (p, high, 8);
 +      digit = wi::extract_uhwi (cst, prec - 1, 1);
 +      stabstr_C ('0' + digit);
 +    }
 +  else if (res_pres == 2)
 +    {
 +      digit = wi::extract_uhwi (cst, prec - 2, 2);
 +      stabstr_C ('0' + digit);
      }
  
 -  obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
 +  prec -= res_pres;
 +  for (i = prec - 3; i <= 0; i = i - 3)
 +    {
 +      digit = wi::extract_uhwi (cst, i, 3);
 +      stabstr_C ('0' + digit);
 +    }
  }
  
  /* Called whenever it is safe to break a stabs string into multiple
@@@ -1470,9 -1519,9 +1470,9 @@@ dbxout_type_fields (tree type
          /* Omit fields whose position or size are variable or too large to
             represent.  */
          || (TREE_CODE (tem) == FIELD_DECL
 -            && (! host_integerp (bit_position (tem), 0)
 +            && (! tree_fits_shwi_p (bit_position (tem))
                  || ! DECL_SIZE (tem)
 -                || ! host_integerp (DECL_SIZE (tem), 1))))
 +                || ! tree_fits_uhwi_p (DECL_SIZE (tem)))))
        continue;
  
        else if (TREE_CODE (tem) != CONST_DECL)
              stabstr_C (',');
              stabstr_D (int_bit_position (tem));
              stabstr_C (',');
 -            stabstr_D (tree_low_cst (DECL_SIZE (tem), 1));
 +            stabstr_D (tree_to_uhwi (DECL_SIZE (tem)));
              stabstr_C (';');
            }
        }
@@@ -1561,9 -1610,9 +1561,9 @@@ dbxout_type_method_1 (tree decl
    stabstr_C (c1);
    stabstr_C (c2);
  
 -  if (DECL_VINDEX (decl) && host_integerp (DECL_VINDEX (decl), 0))
 +  if (DECL_VINDEX (decl) && tree_fits_shwi_p (DECL_VINDEX (decl)))
      {
 -      stabstr_D (tree_low_cst (DECL_VINDEX (decl), 0));
 +      stabstr_D (tree_to_shwi (DECL_VINDEX (decl)));
        stabstr_C (';');
        dbxout_type (DECL_CONTEXT (decl), 0);
        stabstr_C (';');
@@@ -1669,23 -1718,23 +1669,23 @@@ dbxout_range_type (tree type, tree low
      }
  
    stabstr_C (';');
 -  if (low && host_integerp (low, 0))
 +  if (low && tree_fits_shwi_p (low))
      {
        if (print_int_cst_bounds_in_octal_p (type, low, high))
          stabstr_O (low);
        else
 -        stabstr_D (tree_low_cst (low, 0));
 +        stabstr_D (tree_to_shwi (low));
      }
    else
      stabstr_C ('0');
  
    stabstr_C (';');
 -  if (high && host_integerp (high, 0))
 +  if (high && tree_fits_shwi_p (high))
      {
        if (print_int_cst_bounds_in_octal_p (type, low, high))
          stabstr_O (high);
        else
 -        stabstr_D (tree_low_cst (high, 0));
 +        stabstr_D (tree_to_shwi (high));
        stabstr_C (';');
      }
    else
@@@ -1815,7 -1864,7 +1815,7 @@@ dbxout_type (tree type, int full
         Sun dbx crashes if we do.  */
        if (! full || !COMPLETE_TYPE_P (type)
          /* No way in DBX fmt to describe a variable size.  */
 -        || ! host_integerp (TYPE_SIZE (type), 1))
 +        || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
        return;
        break;
      case TYPE_DEFINED:
         && !full)
        || !COMPLETE_TYPE_P (type)
        /* No way in DBX fmt to describe a variable size.  */
 -      || ! host_integerp (TYPE_SIZE (type), 1))
 +      || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
        {
        typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
        return;
             && !full)
            || !COMPLETE_TYPE_P (type)
            /* No way in DBX fmt to describe a variable size.  */
 -          || ! host_integerp (TYPE_SIZE (type), 1))
 +          || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
          {
            /* If the type is just a cross reference, output one
               and mark the type as partially described.
                         offset within the vtable where we must look
                         to find the necessary adjustment.  */
                      stabstr_D
 -                      (tree_low_cst (BINFO_VPTR_FIELD (child), 0)
 +                      (tree_to_shwi (BINFO_VPTR_FIELD (child))
                         * BITS_PER_UNIT);
                    else
 -                    stabstr_D (tree_low_cst (BINFO_OFFSET (child), 0)
 +                    stabstr_D (tree_to_shwi (BINFO_OFFSET (child))
                                       * BITS_PER_UNIT);
                    stabstr_C (',');
                    dbxout_type (BINFO_TYPE (child), 0);
                    stabstr_C (':');
                    dbxout_type (BINFO_TYPE (child), full);
                    stabstr_C (',');
 -                  stabstr_D (tree_low_cst (BINFO_OFFSET (child), 0)
 +                  stabstr_D (tree_to_shwi (BINFO_OFFSET (child))
                                     * BITS_PER_UNIT);
                    stabstr_C (',');
                    stabstr_D
 -                    (tree_low_cst (TYPE_SIZE (BINFO_TYPE (child)), 0)
 +                    (tree_to_shwi (TYPE_SIZE (BINFO_TYPE (child)))
                       * BITS_PER_UNIT);
                    stabstr_C (';');
                  }
            if (TREE_CODE (value) == CONST_DECL)
              value = DECL_INITIAL (value);
  
 -        if (TREE_INT_CST_HIGH (value) == 0)
 -          stabstr_D (TREE_INT_CST_LOW (value));
 -        else if (TREE_INT_CST_HIGH (value) == -1
 -                 && (HOST_WIDE_INT) TREE_INT_CST_LOW (value) < 0)
 -          stabstr_D (TREE_INT_CST_LOW (value));
 +        if (cst_fits_shwi_p (value))
 +          stabstr_D (tree_to_hwi (value));
          else
            stabstr_O (value);
  
@@@ -2428,7 -2480,7 +2428,7 @@@ dbxout_expand_expr (tree expr
             return NULL, otherwise stabs might reference an undefined
             symbol.  */
          struct varpool_node *node = varpool_get_node (expr);
-         if (!node || !node->symbol.definition)
+         if (!node || !node->definition)
            return NULL;
        }
        /* FALLTHRU */
          return NULL;
        if (offset != NULL)
          {
 -          if (!host_integerp (offset, 0))
 +          if (!tree_fits_shwi_p (offset))
              return NULL;
 -          x = adjust_address_nv (x, mode, tree_low_cst (offset, 0));
 +          x = adjust_address_nv (x, mode, tree_to_shwi (offset));
          }
        if (bitpos != 0)
          x = adjust_address_nv (x, mode, bitpos / BITS_PER_UNIT);
@@@ -2744,7 -2796,7 +2744,7 @@@ dbxout_symbol (tree decl, int local ATT
                /* Do not generate a tag for records of variable size,
                   since this type can not be properly described in the
                   DBX format, and it confuses some tools such as objdump.  */
 -              && host_integerp (TYPE_SIZE (type), 1))
 +              && tree_fits_uhwi_p (TYPE_SIZE (type)))
              {
                tree name = TYPE_NAME (type);
                if (TREE_CODE (name) == TYPE_DECL)
         ??? Why do we skip emitting the type and location in this case?  */
        if (TREE_STATIC (decl) && TREE_READONLY (decl)
          && DECL_INITIAL (decl) != 0
 -        && host_integerp (DECL_INITIAL (decl), 0)
 +        && tree_fits_shwi_p (DECL_INITIAL (decl))
          && ! TREE_ASM_WRITTEN (decl)
          && (DECL_FILE_SCOPE_P (decl)
              || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
          if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE
              || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
            {
 -            HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl));
 +            HOST_WIDE_INT ival = tree_to_hwi (DECL_INITIAL (decl));
  
              dbxout_begin_complex_stabs ();
              dbxout_symbol_name (decl, NULL, 'c');
diff --combined gcc/doc/generic.texi
index a78c19d3781686b7ecef9e2bf893d54c7bb23cff,73dd1236412468e38a1e9b081c4e67d2f6000a41..238a9cead89123f725c9bb73778d6bb81bcbd4f2
@@@ -1022,12 -1022,10 +1022,12 @@@ As this example indicates, the operand
  @node Constant expressions
  @subsection Constant expressions
  @tindex INTEGER_CST
 -@findex TREE_INT_CST_HIGH
 -@findex TREE_INT_CST_LOW
 -@findex tree_int_cst_lt
 -@findex tree_int_cst_equal
 +@tindex tree_fits_uhwi_p
 +@tindex tree_fits_shwi_p
 +@tindex tree_fits_hwi_p
 +@tindex tree_to_uhwi
 +@tindex tree_to_shwi
 +@tindex tree_to_hwi
  @tindex REAL_CST
  @tindex FIXED_CST
  @tindex COMPLEX_CST
@@@ -1046,20 -1044,36 +1046,20 @@@ These nodes represent integer constants
  constants is obtained with @code{TREE_TYPE}; they are not always of type
  @code{int}.  In particular, @code{char} constants are represented with
  @code{INTEGER_CST} nodes.  The value of the integer constant @code{e} is
 -given by
 -@smallexample
 -((TREE_INT_CST_HIGH (e) << HOST_BITS_PER_WIDE_INT)
 -+ TREE_INST_CST_LOW (e))
 -@end smallexample
 -@noindent
 -HOST_BITS_PER_WIDE_INT is at least thirty-two on all platforms.  Both
 -@code{TREE_INT_CST_HIGH} and @code{TREE_INT_CST_LOW} return a
 -@code{HOST_WIDE_INT}.  The value of an @code{INTEGER_CST} is interpreted
 -as a signed or unsigned quantity depending on the type of the constant.
 -In general, the expression given above will overflow, so it should not
 -be used to calculate the value of the constant.
 -
 -The variable @code{integer_zero_node} is an integer constant with value
 -zero.  Similarly, @code{integer_one_node} is an integer constant with
 -value one.  The @code{size_zero_node} and @code{size_one_node} variables
 -are analogous, but have type @code{size_t} rather than @code{int}.
 -
 -The function @code{tree_int_cst_lt} is a predicate which holds if its
 -first argument is less than its second.  Both constants are assumed to
 -have the same signedness (i.e., either both should be signed or both
 -should be unsigned.)  The full width of the constant is used when doing
 -the comparison; the usual rules about promotions and conversions are
 -ignored.  Similarly, @code{tree_int_cst_equal} holds if the two
 -constants are equal.  The @code{tree_int_cst_sgn} function returns the
 -sign of a constant.  The value is @code{1}, @code{0}, or @code{-1}
 -according on whether the constant is greater than, equal to, or less
 -than zero.  Again, the signedness of the constant's type is taken into
 -account; an unsigned constant is never less than zero, no matter what
 -its bit-pattern.
 +represented in an array of HOST_WIDE_INT.   There are enough elements
 +in the array to represent the value without taking extra elements for
 +redundant 0s or -1.
 +
 +The functions @code{tree_fits_uhwi_p}, @code{tree_fits_shwi_p}, and
 +@code{tree_fits_hwi_p} can be used to tell if the value is small
 +enough to fit in a HOST_WIDE_INT, as either a signed value, an unsiged
 +value or a value whose sign is given as a parameter.  The value can
 +then be extracted using the @code{tree_to_uhwi}, @code{tree_to_shwi},
 +or @code{tree_to_hwi}.  The @code{tree_to_hwi} comes in both checked
 +and unchecked flavors.  However, when the value is used in a context
 +where it may represent a value that is larger than can be represented
 +in HOST_BITS_PER_WIDE_INT bits, the wide_int class should be used to
 +manipulate the constant.
  
  @item REAL_CST
  
@@@ -1265,6 -1279,7 +1265,7 @@@ the byte offset of the field, but shoul
  @tindex SAVE_EXPR
  @tindex TARGET_EXPR
  @tindex VA_ARG_EXPR
+ @tindex ANNOTATE_EXPR
  
  @table @code
  @item NEGATE_EXPR
@@@ -1678,8 -1693,13 +1679,13 @@@ mechanism.  It represents expressions l
  Its @code{TREE_TYPE} yields the tree representation for @code{type} and
  its sole argument yields the representation for @code{ap}.
  
+ @item ANNOTATE_EXPR
+ This node is used to attach markers to an expression. The first operand
+ is the annotated expression, the second is an @code{INTEGER_CST} with
+ a value from @code{enum annot_expr_kind}.
  @end table
  
  @node Vectors
  @subsection Vectors
  @tindex VEC_LSHIFT_EXPR
@@@ -3146,6 -3166,30 +3152,30 @@@ several statements chained together
  Used to represent a @code{break} statement.  There are no additional
  fields.
  
+ @item CILK_SPAWN_STMT
+ Used to represent a spawning function in the Cilk Plus language extension.  
+ This tree has one field that holds the name of the spawning function.
+ @code{_Cilk_spawn} can be written in C in the following way:
+ @smallexample
+ @code{_Cilk_spawn} <function_name> (<parameters>);
+ @end smallexample
+ Detailed description for usage and functionality of @code{_Cilk_spawn} can be 
+ found at http://www.cilkplus.org
+ @item CILK_SYNC_STMT
+ This statement is part of the Cilk Plus language extension.  It indicates that
+ the current function cannot continue in parallel with its spawned children.  
+ There are no additional fields.  @code{_Cilk_sync} can be written in C in the 
+ following way:
+ @smallexample
+ @code{_Cilk_sync};
+ @end smallexample
  @item CLEANUP_STMT
  
  Used to represent an action that should take place upon exit from the
diff --combined gcc/doc/rtl.texi
index 03732f1a2d42a877b2d08004207d260931d5fa11,df2bb6806dc2740db4e0c7ae875f8a24359acaa8..8dc531c35d29e6f21fa004790081a805481192a2
@@@ -1295,6 -1295,12 +1295,12 @@@ These modes stand for a complex number 
  values.  The integer values are in @code{QImode}, @code{HImode},
  @code{SImode}, @code{DImode}, @code{TImode}, and @code{OImode},
  respectively.
+ @findex BND32mode
+ @findex BND64mode
+ @item BND32mode BND64mode
+ These modes stand for bounds for pointer of 32 and 64 bit size respectively.
+ Mode size is double pointer mode size.
  @end table
  
  The machine description defines @code{Pmode} as a C macro which expands
@@@ -1382,6 -1388,12 +1388,12 @@@ any @code{CC_MODE} modes listed in the 
  @xref{Jump Patterns},
  also see @ref{Condition Code}.
  
+ @findex MODE_POINTER_BOUNDS
+ @item MODE_POINTER_BOUNDS
+ Pointer bounds modes.  Used to represent values of pointer bounds type.
+ Operations in these modes may be executed as NOPs depending on hardware
+ features and environment setup.
  @findex MODE_RANDOM
  @item MODE_RANDOM
  This is a catchall mode class for modes which don't fit into the above
@@@ -1529,22 -1541,17 +1541,22 @@@ Similarly, there is only one object fo
  
  @findex const_double
  @item (const_double:@var{m} @var{i0} @var{i1} @dots{})
 -Represents either a floating-point constant of mode @var{m} or an
 -integer constant too large to fit into @code{HOST_BITS_PER_WIDE_INT}
 -bits but small enough to fit within twice that number of bits (GCC
 -does not provide a mechanism to represent even larger constants).  In
 -the latter case, @var{m} will be @code{VOIDmode}.  For integral values
 -constants for modes with more bits than twice the number in
 -@code{HOST_WIDE_INT} the implied high order bits of that constant are
 -copies of the top bit of @code{CONST_DOUBLE_HIGH}.  Note however that
 -integral values are neither inherently signed nor inherently unsigned;
 -where necessary, signedness is determined by the rtl operation
 -instead.
 +This represents either a floating-point constant of mode @var{m} or
 +(on ports older ports that do not define
 +@code{TARGET_SUPPORTS_WIDE_INT}) an integer constant too large to fit
 +into @code{HOST_BITS_PER_WIDE_INT} bits but small enough to fit within
 +twice that number of bits (GCC does not provide a mechanism to
 +represent even larger constants).  In the latter case, @var{m} will be
 +@code{VOIDmode}.  For integral values constants for modes with more
 +bits than twice the number in @code{HOST_WIDE_INT} the implied high
 +order bits of that constant are copies of the top bit of
 +@code{CONST_DOUBLE_HIGH}.  Note however that integral values are
 +neither inherently signed nor inherently unsigned; where necessary,
 +signedness is determined by the rtl operation instead.
 +
 +On more modern ports, @code{CONST_DOUBLE} only represents floating
 +point values.  New ports define to @code{TARGET_SUPPORTS_WIDE_INT} to
 +make this designation.
  
  @findex CONST_DOUBLE_LOW
  If @var{m} is @code{VOIDmode}, the bits of the value are stored in
@@@ -1559,37 -1566,6 +1571,37 @@@ machine's or host machine's floating po
  the precise bit pattern used by the target machine, use the macro
  @code{REAL_VALUE_TO_TARGET_DOUBLE} and friends (@pxref{Data Output}).
  
 +@findex CONST_WIDE_INT
 +@item (const_wide_int:@var{m} @var{nunits} @var{elt0} @dots{})
 +This contains an array of @code{HOST_WIDE_INTS} that is large enough
 +to hold any constant that can be represented on the target.  This form
 +of rtl is only used on targets that define
 +@code{TARGET_SUPPORTS_WIDE_INT} to be non zero and then
 +@code{CONST_DOUBLES} are only used to hold floating point values.  If
 +the target leaves @code{TARGET_SUPPORTS_WIDE_INT} defined as 0,
 +@code{CONST_WIDE_INT}s are not used and @code{CONST_DOUBLE}s are as
 +they were before.
 +
 +The values are stored in a compressed format.   The higher order
 +0s or -1s are not represented if they are just the logical sign
 +extension of the number that is represented.   
 +
 +@findex CONST_WIDE_INT_VEC
 +@item CONST_WIDE_INT_VEC (@var{code})
 +Returns the entire array of @code{HOST_WIDE_INT}s that are used to
 +store the value.   This macro should be rarely used.
 +
 +@findex CONST_WIDE_INT_NUNITS
 +@item CONST_WIDE_INT_NUNITS (@var{code})
 +The number of @code{HOST_WIDE_INT}s used to represent the number.
 +Note that this generally be smaller than the number of
 +@code{HOST_WIDE_INT}s implied by the mode size.
 +
 +@findex CONST_WIDE_INT_ELT
 +@item CONST_WIDE_INT_NUNITS (@var{code},@var{i})
 +Returns the @code{i}th element of the array.   Element 0 is contains
 +the low order bits of the constant.
 +
  @findex const_fixed
  @item (const_fixed:@var{m} @dots{})
  Represents a fixed-point constant of mode @var{m}.
diff --combined gcc/doc/tm.texi
index ae99c12ecadd15960277d8e3975a96eed648cdcc,fc5e1a544b3207e8b5a174c3c8d0e2cb2ae15adb..79111346a03206314f3a0fa8bbd22e9fb166201f
@@@ -768,6 -768,10 +768,10 @@@ Define this macro to 1 if your target n
  is 0.
  @end defmac
  
+ @deftypefn {Target Hook} bool TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P (void)
+ Returns true if the target supports IEEE 754 floating-point exceptions and rounding modes, false otherwise.  This is intended to relate to the @code{float} and @code{double} types, but not necessarily @code{long double}. By default, returns true if the @code{adddf3} instruction pattern is available and false otherwise, on the assumption that hardware floating point supports exceptions and rounding modes but software floating point does not.
+ @end deftypefn
  @node Per-Function Data
  @section Defining data structures for per-function information.
  @cindex per-function data
@@@ -4334,6 -4338,13 +4338,13 @@@ This hook returns the va_list type of t
  The default version of this hook returns @code{va_list_type_node}.
  @end deftypefn
  
+ @deftypefn {Target Hook} tree TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE (tree @var{fndecl})
+ This hook returns size for @code{va_list} object in function specified
+ by @var{fndecl}.  This hook is used by Pointer Bounds Checker to build bounds
+ for @code{va_list} object.  Return @code{integer_zero_node} if no bounds
+ should be used (e.g. @code{va_list} is a scalar pointer to the stack).
+ @end deftypefn
  @deftypefn {Target Hook} tree TARGET_CANONICAL_VA_LIST_TYPE (tree @var{type})
  This hook returns the va_list type of the calling convention specified by the
  type of @var{type}. If @var{type} is not a valid va_list type, it returns
@@@ -5151,6 -5162,26 +5162,26 @@@ defined, then define this hook to retur
  Otherwise, you should not define this hook.
  @end deftypefn
  
+ @deftypefn {Target Hook} rtx TARGET_LOAD_BOUNDS_FOR_ARG (rtx @var{slot}, rtx @var{arg}, rtx @var{slot_no})
+ This hook is used by expand pass to emit insn to load bounds of
+ @var{arg} passed in @var{slot}.  Expand pass uses this hook in case
+ bounds of @var{arg} are not passed in register.  If @var{slot} is a
+ memory, then bounds are loaded as for regular pointer loaded from
+ memory.  If @var{slot} is not a memory then @var{slot_no} is an integer
+ constant holding number of the target dependent special slot which
+ should be used to obtain bounds.  Hook returns RTX holding loaded bounds.
+ @end deftypefn
+ @deftypefn {Target Hook} void TARGET_STORE_BOUNDS_FOR_ARG (rtx @var{arg}, rtx @var{slot}, rtx @var{bounds}, rtx @var{slot_no})
+ This hook is used by expand pass to emit insns to store @var{bounds} of
+ @var{arg} passed in @var{slot}.  Expand pass uses this hook in case
+ @var{bounds} of @var{arg} are not passed in register.  If @var{slot} is a
+ memory, then @var{bounds} are stored as for regular pointer stored in
+ memory.  If @var{slot} is not a memory then @var{slot_no} is an integer
+ constant holding number of the target dependent special slot which
+ should be used to store @var{bounds}.
+ @end deftypefn
  @node Trampolines
  @section Trampolines for Nested Functions
  @cindex trampolines for nested functions
@@@ -9641,8 -9672,14 +9672,8 @@@ Returns the negative of the floating po
  Returns the absolute value of @var{x}.
  @end deftypefn
  
 -@deftypefn Macro void REAL_VALUE_TO_INT (HOST_WIDE_INT @var{low}, HOST_WIDE_INT @var{high}, REAL_VALUE_TYPE @var{x})
 -Converts a floating point value @var{x} into a double-precision integer
 -which is then stored into @var{low} and @var{high}.  If the value is not
 -integral, it is truncated.
 -@end deftypefn
 -
 -@deftypefn Macro void REAL_VALUE_FROM_INT (REAL_VALUE_TYPE @var{x}, HOST_WIDE_INT @var{low}, HOST_WIDE_INT @var{high}, enum machine_mode @var{mode})
 -Converts a double-precision integer found in @var{low} and @var{high},
 +@deftypefn Macro void REAL_VALUE_FROM_INT (REAL_VALUE_TYPE @var{x}, HOST_WIDE_INT @var{val}, enum machine_mode @var{mode})
 +Converts a double-precision integer found in @var{val},
  into a floating point value which is then stored into @var{x}.  The
  value is truncated to fit in mode @var{mode}.
  @end deftypefn
@@@ -10901,6 -10938,96 +10932,96 @@@ ignored.  This function should return t
  built-in function.
  @end deftypefn
  
+ @deftypefn {Target Hook} tree TARGET_BUILTIN_CHKP_FUNCTION (unsigned @var{fcode})
+ This hook allows target to redefine built-in functions used by
+ Pointer Bounds Checker for code instrumentation.  Hook should return
+ fndecl of function implementing generic builtin whose code is
+ passed in @var{fcode}.  Currently following built-in functions are
+ obtained using this hook:
+ @deftypefn {Built-in Function} bnd __chkp_bndmk (const void *@var{lb}, size_t @var{size})
+ Function code - BUILT_IN_CHKP_BNDMK.  This built-in function is used
+ by Pointer Bounds Checker to create bound values.  @var{lb} holds low
+ bound of the resulting bounds.  @var{size} holds size of created bounds.
+ @end deftypefn
+ @deftypefn {Built-in Function} void __chkp_bndstx (const void **@var{loc}, const void *@var{ptr}, bnd @var{b})
+ Function code - @code{BUILT_IN_CHKP_BNDSTX}.  This built-in function is used
+ by Pointer Bounds Checker to store bounds @var{b} for pointer @var{ptr}
+ stored by address @var{loc}.
+ @end deftypefn
+ @deftypefn {Built-in Function} bnd __chkp_bndldx (const void **@var{loc}, const void *@var{ptr})
+ Function code - @code{BUILT_IN_CHKP_BNDLDX}.  This built-in function is used
+ by Pointer Bounds Checker to get bounds of pointer @var{ptr} loaded by
+ address @var{loc}.
+ @end deftypefn
+ @deftypefn {Built-in Function} void __chkp_bndcl (bnd @var{b}, const void *@var{ptr})
+ Function code - @code{BUILT_IN_CHKP_BNDCL}.  This built-in function is used
+ by Pointer Bounds Checker to perform check for pointer @var{ptr} against
+ lower bound of bounds @var{b}.
+ @end deftypefn
+ @deftypefn {Built-in Function} void __chkp_bndcu (bnd @var{b}, const void *@var{ptr})
+ Function code - @code{BUILT_IN_CHKP_BNDCU}.  This built-in function is used
+ by Pointer Bounds Checker to perform check for pointer @var{ptr} against
+ upper bound of bounds @var{b}.
+ @end deftypefn
+ @deftypefn {Built-in Function} bnd __chkp_bndret (void *@var{ptr})
+ Function code - @code{BUILT_IN_CHKP_BNDRET}.  This built-in function is used
+ by Pointer Bounds Checker to obtain bounds returned by call statement.
+ @var{ptr} passed to buil-in is @code{SSA_NAME} returned by call.
+ @end deftypefn
+ @deftypefn {Built-in Function} bnd __chkp_arg_bnd (void *@var{arg})
+ Function code - @code{BUILT_IN_CHKP_ARG_BND}.   This built-in function is
+ used by Pointer Bounds Checker to obtain bounds passed for input argument.
+ @var{arg} is default @code{SSA_NAME} of the @code{PARM_DECL} whose
+ bounds we want to obtain.
+ @end deftypefn
+ @deftypefn {Built-in Function} bnd __chkp_intersect (bnd @var{b1}, bnd @var{b2})
+ Function code - @code{BUILT_IN_CHKP_INTERSECT}.  This built-in function
+ returns intersection of bounds @var{b1} and @var{b2}.
+ @end deftypefn
+ @deftypefn {Built-in Function} bnd __chkp_narrow (const void *@var{ptr}, bnd @var{b}, size_t @var{s})
+ Function code - @code{BUILT_IN_CHKP_NARROW}.  This built-in function
+ returns intersection of bounds @var{b} and
+ [@var{ptr}, @var{ptr} + @var{s} - @code{1}].
+ @end deftypefn
+ @deftypefn {Built-in Function} void *__chkp_set_bounds (const void *@var{ptr}, size_t @var{s})
+ Function code - @code{BUILT_IN_CHKP_SET_PTR_BOUNDS}.  This built-in function
+ returns @var{ptr} with bounds [@var{ptr}, @var{ptr} + @var{s} - @code{1}].
+ @end deftypefn
+ @deftypefn {Built-in Function} size_t __chkp_sizeof (const void *@var{ptr})
+ Function code - @code{BUILT_IN_CHKP_SIZEOF}.  This built-in function
+ returns size of object referenced by @var{ptr}. @var{ptr} is always
+ @code{ADDR_EXPR} of @code{VAR_DECL}.  This built-in is used by
+ Pointer Boudns Checker when bounds of object cannot be computed statically
+ (e.g. object has incomplete type).
+ @end deftypefn
+ @deftypefn {Built-in Function} const void *__chkp_extract_lower (bnd @var{b})
+ Function code - @code{BUILT_IN_CHKP_EXTRACT_LOWER}.  This built-in function
+ returns lower bound of bounds @var{b}.
+ @end deftypefn
+ @deftypefn {Built-in Function} const void *__chkp_extract_upper (bnd @var{b})
+ Function code - @code{BUILT_IN_CHKP_EXTRACT_UPPER}.  This built-in function
+ returns upper bound of bounds @var{b}.
+ @end deftypefn
+ @end deftypefn
+ @deftypefn {Target Hook} tree TARGET_CHKP_BOUND_TYPE (void)
+ Return type to be used for bounds
+ @end deftypefn
+ @deftypefn {Target Hook} {enum machine_mode} TARGET_CHKP_BOUND_MODE (void)
+ Return mode to be used for bounds.
+ @end deftypefn
  @deftypefn {Target Hook} tree TARGET_RESOLVE_OVERLOADED_BUILTIN (unsigned int @var{loc}, tree @var{fndecl}, void *@var{arglist})
  Select a replacement for a machine specific built-in function that
  was set up by @samp{TARGET_INIT_BUILTINS}.  This is done
@@@ -11347,50 -11474,3 +11468,50 @@@ It returns true if the target supports 
  The support includes the assembler, linker and dynamic linker.
  The default value of this hook is based on target's libc.
  @end deftypefn
 +
 +@defmac TARGET_SUPPORTS_WIDE_INT
 +
 +On older ports, large integers are stored in @code{CONST_DOUBLE} rtl
 +objects.  Newer ports define @code{TARGET_SUPPORTS_WIDE_INT} to be non
 +zero to indicate that large integers are stored in
 +@code{CONST_WIDE_INT} rtl objects.  The @code{CONST_WIDE_INT} allows
 +very large integer constants to be represented.  @code{CONST_DOUBLE}
 +are limited to twice the size of host's @code{HOST_WIDE_INT}
 +representation.
 +
 +Converting a port mostly requires looking for the places where
 +@code{CONST_DOUBLES} are used with @code{VOIDmode} and replacing that
 +code with code that accesses @code{CONST_WIDE_INT}s.  @samp{"grep -i
 +const_double"} at the port level gets you to 95% of the changes that
 +need to be made.  There are a few places that require a deeper look.
 +
 +@itemize @bullet
 +@item
 +There is no equivalent to @code{hval} and @code{lval} for
 +@code{CONST_WIDE_INT}s.  This would be difficult to express in the md
 +language since there are a variable number of elements.
 +
 +Most ports only check that @code{hval} is either 0 or -1 to see if the
 +value is small.  As mentioned above, this will no longer be necessary
 +since small constants are always @code{CONST_INT}.  Of course there
 +are still a few exceptions, the alpha's constraint used by the zap
 +instruction certainly requires careful examination by C code.
 +However, all the current code does is pass the hval and lval to C
 +code, so evolving the c code to look at the @code{CONST_WIDE_INT} is
 +not really a large change.
 +
 +@item
 +Because there is no standard template that ports use to materialize
 +constants, there is likely to be some futzing that is unique to each
 +port in this code.
 +
 +@item
 +The rtx costs may have to be adjusted to properly account for larger
 +constants that are represented as @code{CONST_WIDE_INT}.
 +@end itemize
 +
 +All and all it does not takes long to convert ports that the
 +maintainer is familiar with.
 +
 +@end defmac
 +
diff --combined gcc/doc/tm.texi.in
index 368afd6b1e73cc38f6853049f2c1fc1bf563f370,a641f3dcd30cf51916aafbd1926dafa8f21d5405..78a4e39382c4e8b5ec909ee8987ae0a32e108206
@@@ -744,6 -744,8 +744,8 @@@ Define this macro to 1 if your target n
  is 0.
  @end defmac
  
+ @hook TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P
  @node Per-Function Data
  @section Defining data structures for per-function information.
  @cindex per-function data
@@@ -3694,6 -3696,8 +3696,8 @@@ stack
  
  @hook TARGET_FN_ABI_VA_LIST
  
+ @hook TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE
  @hook TARGET_CANONICAL_VA_LIST_TYPE
  
  @hook TARGET_GIMPLIFY_VA_ARG_EXPR
@@@ -4064,6 -4068,10 +4068,10 @@@ These machine description macros help i
  
  @hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED
  
+ @hook TARGET_LOAD_BOUNDS_FOR_ARG
+ @hook TARGET_STORE_BOUNDS_FOR_ARG
  @node Trampolines
  @section Trampolines for Nested Functions
  @cindex trampolines for nested functions
@@@ -7333,8 -7341,14 +7341,8 @@@ Returns the negative of the floating po
  Returns the absolute value of @var{x}.
  @end deftypefn
  
 -@deftypefn Macro void REAL_VALUE_TO_INT (HOST_WIDE_INT @var{low}, HOST_WIDE_INT @var{high}, REAL_VALUE_TYPE @var{x})
 -Converts a floating point value @var{x} into a double-precision integer
 -which is then stored into @var{low} and @var{high}.  If the value is not
 -integral, it is truncated.
 -@end deftypefn
 -
 -@deftypefn Macro void REAL_VALUE_FROM_INT (REAL_VALUE_TYPE @var{x}, HOST_WIDE_INT @var{low}, HOST_WIDE_INT @var{high}, enum machine_mode @var{mode})
 -Converts a double-precision integer found in @var{low} and @var{high},
 +@deftypefn Macro void REAL_VALUE_FROM_INT (REAL_VALUE_TYPE @var{x}, HOST_WIDE_INT @var{val}, enum machine_mode @var{mode})
 +Converts a double-precision integer found in @var{val},
  into a floating point value which is then stored into @var{x}.  The
  value is truncated to fit in mode @var{mode}.
  @end deftypefn
@@@ -8178,6 -8192,10 +8186,10 @@@ to by @var{ce_info}
  
  @hook TARGET_EXPAND_BUILTIN
  
+ @hook TARGET_BUILTIN_CHKP_FUNCTION
+ @hook TARGET_CHKP_BOUND_TYPE
+ @hook TARGET_CHKP_BOUND_MODE
  @hook TARGET_RESOLVE_OVERLOADED_BUILTIN
  
  @hook TARGET_FOLD_BUILTIN
@@@ -8382,50 -8400,3 +8394,50 @@@ and the associated definitions of thos
  @hook TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
  
  @hook TARGET_HAS_IFUNC_P
 +
 +@defmac TARGET_SUPPORTS_WIDE_INT
 +
 +On older ports, large integers are stored in @code{CONST_DOUBLE} rtl
 +objects.  Newer ports define @code{TARGET_SUPPORTS_WIDE_INT} to be non
 +zero to indicate that large integers are stored in
 +@code{CONST_WIDE_INT} rtl objects.  The @code{CONST_WIDE_INT} allows
 +very large integer constants to be represented.  @code{CONST_DOUBLE}
 +are limited to twice the size of host's @code{HOST_WIDE_INT}
 +representation.
 +
 +Converting a port mostly requires looking for the places where
 +@code{CONST_DOUBLES} are used with @code{VOIDmode} and replacing that
 +code with code that accesses @code{CONST_WIDE_INT}s.  @samp{"grep -i
 +const_double"} at the port level gets you to 95% of the changes that
 +need to be made.  There are a few places that require a deeper look.
 +
 +@itemize @bullet
 +@item
 +There is no equivalent to @code{hval} and @code{lval} for
 +@code{CONST_WIDE_INT}s.  This would be difficult to express in the md
 +language since there are a variable number of elements.
 +
 +Most ports only check that @code{hval} is either 0 or -1 to see if the
 +value is small.  As mentioned above, this will no longer be necessary
 +since small constants are always @code{CONST_INT}.  Of course there
 +are still a few exceptions, the alpha's constraint used by the zap
 +instruction certainly requires careful examination by C code.
 +However, all the current code does is pass the hval and lval to C
 +code, so evolving the c code to look at the @code{CONST_WIDE_INT} is
 +not really a large change.
 +
 +@item
 +Because there is no standard template that ports use to materialize
 +constants, there is likely to be some futzing that is unique to each
 +port in this code.
 +
 +@item
 +The rtx costs may have to be adjusted to properly account for larger
 +constants that are represented as @code{CONST_WIDE_INT}.
 +@end itemize
 +
 +All and all it does not takes long to convert ports that the
 +maintainer is familiar with.
 +
 +@end defmac
 +
diff --combined gcc/dwarf2out.c
index 54fc6f7320d37599c7646f99454759607d622169,5ef7bd2034dd553b597e7a7522c8fa41cfa14101..07cb28e8d3c4a6bb69d12649c12e20e6073e8708
@@@ -93,6 -93,7 +93,7 @@@ along with GCC; see the file COPYING3
  #include "dumpfile.h"
  #include "opts.h"
  #include "tree-dfa.h"
+ #include "gdb/gdb-index.h"
  
  static void dwarf2out_source_line (unsigned int, const char *, int, bool);
  static rtx last_var_location_insn;
@@@ -347,16 -348,6 +348,16 @@@ dump_struct_debug (tree type, enum debu
  
  #endif
  
 +/* Get the number of host wide ints needed to represent the precision
 +   of the number.  */
 +
 +static unsigned int
 +get_full_len (const wide_int &op)
 +{
 +  return ((op.get_precision () + HOST_BITS_PER_WIDE_INT - 1)
 +        / HOST_BITS_PER_WIDE_INT);
 +}
 +
  static bool
  should_emit_struct_debug (tree type, enum debug_info_usage usage)
  {
@@@ -1392,9 -1383,6 +1393,9 @@@ dw_val_equal_p (dw_val_node *a, dw_val_
        return (a->v.val_double.high == b->v.val_double.high
              && a->v.val_double.low == b->v.val_double.low);
  
 +    case dw_val_class_wide_int:
 +      return *a->v.val_wide == *b->v.val_wide;
 +
      case dw_val_class_vec:
        {
        size_t a_len = a->v.val_vec.elt_size * a->v.val_vec.length;
@@@ -1651,10 -1639,6 +1652,10 @@@ size_of_loc_descr (dw_loc_descr_ref loc
          case dw_val_class_const_double:
            size += HOST_BITS_PER_DOUBLE_INT / BITS_PER_UNIT;
            break;
 +        case dw_val_class_wide_int:
 +          size += (get_full_len (*loc->dw_loc_oprnd2.v.val_wide)
 +                   * HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT);
 +          break;
          default:
            gcc_unreachable ();
          }
@@@ -1832,20 -1816,6 +1833,20 @@@ output_loc_operands (dw_loc_descr_ref l
                                 second, NULL);
          }
          break;
 +      case dw_val_class_wide_int:
 +        {
 +          int i;
 +          int len = get_full_len (*val2->v.val_wide);
 +          if (WORDS_BIG_ENDIAN)
 +            for (i = len; i >= 0; --i)
 +              dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
 +                                   val2->v.val_wide->elt (i), NULL);
 +          else
 +            for (i = 0; i < len; ++i)
 +              dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
 +                                   val2->v.val_wide->elt (i), NULL);
 +        }
 +        break;
        case dw_val_class_addr:
          gcc_assert (val1->v.val_unsigned == DWARF2_ADDR_SIZE);
          dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, val2->v.val_addr, NULL);
              dw2_asm_output_data (l, second, NULL);
            }
            break;
 +        case dw_val_class_wide_int:
 +          {
 +            int i;
 +            int len = get_full_len (*val2->v.val_wide);
 +            l = HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
 +
 +            dw2_asm_output_data (1, len * l, NULL);
 +            if (WORDS_BIG_ENDIAN)
 +              for (i = len; i >= 0; --i)
 +                dw2_asm_output_data (l, val2->v.val_wide->elt (i), NULL);
 +            else
 +              for (i = 0; i < len; ++i)
 +                dw2_asm_output_data (l, val2->v.val_wide->elt (i), NULL);
 +          }
 +          break;
          default:
            gcc_unreachable ();
          }
@@@ -3162,7 -3117,7 +3163,7 @@@ static void add_AT_location_descriptio
  static void add_data_member_location_attribute (dw_die_ref, tree);
  static bool add_const_value_attribute (dw_die_ref, rtx);
  static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
 -static void insert_double (double_int, unsigned char *);
 +static void insert_wide_int (const wide_int &, unsigned char *);
  static void insert_float (const_rtx, unsigned char *);
  static rtx rtl_for_decl_location (tree);
  static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool,
@@@ -3369,10 -3324,14 +3370,14 @@@ new_addr_loc_descr (rtx addr, enum dtpr
  #define DEBUG_DWO_LOC_SECTION  ".debug_loc.dwo"
  #endif
  #ifndef DEBUG_PUBNAMES_SECTION
- #define DEBUG_PUBNAMES_SECTION        ".debug_pubnames"
+ #define DEBUG_PUBNAMES_SECTION        \
+   ((debug_generate_pub_sections == 2) \
+    ? ".debug_gnu_pubnames" : ".debug_pubnames")
  #endif
  #ifndef DEBUG_PUBTYPES_SECTION
- #define DEBUG_PUBTYPES_SECTION        ".debug_pubtypes"
+ #define DEBUG_PUBTYPES_SECTION        \
+   ((debug_generate_pub_sections == 2) \
+    ? ".debug_gnu_pubtypes" : ".debug_pubtypes")
  #endif
  #define DEBUG_NORM_STR_OFFSETS_SECTION ".debug_str_offsets"
  #define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo"
@@@ -3789,21 -3748,6 +3794,21 @@@ AT_unsigned (dw_attr_ref a
    return a->dw_attr_val.v.val_unsigned;
  }
  
 +/* Add an unsigned wide integer attribute value to a DIE.  */
 +
 +static inline void
 +add_AT_wide (dw_die_ref die, enum dwarf_attribute attr_kind,
 +           const wide_int& w)
 +{
 +  dw_attr_node attr;
 +
 +  attr.dw_attr = attr_kind;
 +  attr.dw_attr_val.val_class = dw_val_class_wide_int;
 +  attr.dw_attr_val.v.val_wide = ggc_alloc_cleared_wide_int ();
 +  *attr.dw_attr_val.v.val_wide = w;
 +  add_dwarf_attr (die, &attr);
 +}
 +
  /* Add an unsigned double integer attribute value to a DIE.  */
  
  static inline void
@@@ -4630,6 -4574,16 +4635,16 @@@ is_cxx (void
    return lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus;
  }
  
+ /* Return TRUE if the language is Java.  */
+ static inline bool
+ is_java (void)
+ {
+   unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
+   return lang == DW_LANG_Java;
+ }
  /* Return TRUE if the language is Fortran.  */
  
  static inline bool
@@@ -5368,19 -5322,6 +5383,19 @@@ print_die (dw_die_ref die, FILE *outfil
                   a->dw_attr_val.v.val_double.high,
                   a->dw_attr_val.v.val_double.low);
          break;
 +      case dw_val_class_wide_int:
 +        {
 +          int i = a->dw_attr_val.v.val_wide->get_len ();
 +          fprintf (outfile, "constant (");
 +          gcc_assert (i > 0);
 +          if (a->dw_attr_val.v.val_wide->elt (i) == 0)
 +            fprintf (outfile, "0x");
 +          fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, a->dw_attr_val.v.val_wide->elt (--i));
 +          while (-- i >= 0)
 +            fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX, a->dw_attr_val.v.val_wide->elt (i));
 +          fprintf (outfile, ")");
 +          break;
 +        }
        case dw_val_class_vec:
          fprintf (outfile, "floating-point or vector constant");
          break;
@@@ -5554,9 -5495,6 +5569,9 @@@ attr_checksum (dw_attr_ref at, struct m
      case dw_val_class_const_double:
        CHECKSUM (at->dw_attr_val.v.val_double);
        break;
 +    case dw_val_class_wide_int:
 +      CHECKSUM (*at->dw_attr_val.v.val_wide);
 +      break;
      case dw_val_class_vec:
        CHECKSUM_BLOCK (at->dw_attr_val.v.val_vec.array,
                      (at->dw_attr_val.v.val_vec.length
@@@ -5834,12 -5772,6 +5849,12 @@@ attr_checksum_ordered (enum dwarf_tag t
        CHECKSUM (at->dw_attr_val.v.val_double);
        break;
  
 +    case dw_val_class_wide_int:
 +      CHECKSUM_ULEB128 (DW_FORM_block);
 +      CHECKSUM_ULEB128 (sizeof (*at->dw_attr_val.v.val_wide));
 +      CHECKSUM (*at->dw_attr_val.v.val_wide);
 +      break;
 +
      case dw_val_class_vec:
        CHECKSUM_ULEB128 (DW_FORM_block);
        CHECKSUM_ULEB128 (at->dw_attr_val.v.val_vec.length
@@@ -6322,8 -6254,6 +6337,8 @@@ same_dw_val_p (const dw_val_node *v1, c
      case dw_val_class_const_double:
        return v1->v.val_double.high == v2->v.val_double.high
             && v1->v.val_double.low == v2->v.val_double.low;
 +    case dw_val_class_wide_int:
 +      return *v1->v.val_wide == *v2->v.val_wide;
      case dw_val_class_vec:
        if (v1->v.val_vec.length != v2->v.val_vec.length
          || v1->v.val_vec.elt_size != v2->v.val_vec.elt_size)
@@@ -7857,13 -7787,6 +7872,13 @@@ size_of_die (dw_die_ref die
          if (HOST_BITS_PER_WIDE_INT >= 64)
            size++; /* block */
          break;
 +      case dw_val_class_wide_int:
 +        size += (get_full_len (*a->dw_attr_val.v.val_wide)
 +                 * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR);
 +        if (get_full_len (*a->dw_attr_val.v.val_wide) * HOST_BITS_PER_WIDE_INT
 +            > 64)
 +          size++; /* block */
 +        break;
        case dw_val_class_vec:
          size += constant_size (a->dw_attr_val.v.val_vec.length
                                 * a->dw_attr_val.v.val_vec.elt_size)
@@@ -8052,6 -7975,12 +8067,12 @@@ unmark_all_dies (dw_die_ref die
  static bool
  include_pubname_in_output (vec<pubname_entry, va_gc> *table, pubname_entry *p)
  {
+   /* By limiting gnu pubnames to definitions only, gold can generate a
+      gdb index without entries for declarations, which don't include
+      enough information to be useful.  */
+   if (debug_generate_pub_sections == 2 && is_declaration_die (p->die))
+     return false;
    if (table == pubname_table)
      {
        /* Enumerator names are part of the pubname table, but the
@@@ -8081,11 -8010,12 +8102,12 @@@ size_of_pubnames (vec<pubname_entry, va
    unsigned long size;
    unsigned i;
    pubname_ref p;
+   int space_for_flags = (debug_generate_pub_sections == 2) ? 1 : 0;
  
    size = DWARF_PUBNAMES_HEADER_SIZE;
    FOR_EACH_VEC_ELT (*names, i, p)
      if (include_pubname_in_output (names, p))
-       size += strlen (p->name) + DWARF_OFFSET_SIZE + 1;
+       size += strlen (p->name) + DWARF_OFFSET_SIZE + 1 + space_for_flags;
  
    size += DWARF_OFFSET_SIZE;
    return size;
@@@ -8226,20 -8156,6 +8248,20 @@@ value_format (dw_attr_ref a
        default:
          return DW_FORM_block1;
        }
 +    case dw_val_class_wide_int:
 +      switch (get_full_len (*a->dw_attr_val.v.val_wide) * HOST_BITS_PER_WIDE_INT)
 +      {
 +      case 8:
 +        return DW_FORM_data1;
 +      case 16:
 +        return DW_FORM_data2;
 +      case 32:
 +        return DW_FORM_data4;
 +      case 64:
 +        return DW_FORM_data8;
 +      default:
 +        return DW_FORM_block1;
 +      }
      case dw_val_class_vec:
        switch (constant_size (a->dw_attr_val.v.val_vec.length
                             * a->dw_attr_val.v.val_vec.elt_size))
@@@ -8679,32 -8595,6 +8701,32 @@@ output_die (dw_die_ref die
          }
          break;
  
 +      case dw_val_class_wide_int:
 +        {
 +          int i;
 +          int len = get_full_len (*a->dw_attr_val.v.val_wide);
 +          int l = HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
 +          if (len * HOST_BITS_PER_WIDE_INT > 64)
 +            dw2_asm_output_data (1, get_full_len (*a->dw_attr_val.v.val_wide) * l,
 +                                 NULL);
 +
 +          if (WORDS_BIG_ENDIAN)
 +            for (i = len; i >= 0; --i)
 +              {
 +                dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
 +                                     name);
 +                name = NULL;
 +              }
 +          else
 +            for (i = 0; i < len; ++i)
 +              {
 +                dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
 +                                     name);
 +                name = NULL;
 +              }
 +        }
 +        break;
 +
        case dw_val_class_vec:
          {
            unsigned int elt_size = a->dw_attr_val.v.val_vec.elt_size;
@@@ -9278,6 -9168,76 +9300,76 @@@ add_pubtype (tree decl, dw_die_ref die
      }
  }
  
+ /* Output a single entry in the pubnames table.  */
+ static void
+ output_pubname (dw_offset die_offset, pubname_entry *entry)
+ {
+   dw_die_ref die = entry->die;
+   int is_static = get_AT_flag (die, DW_AT_external) ? 0 : 1;
+   dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset");
+   if (debug_generate_pub_sections == 2)
+     {
+       /* This logic follows gdb's method for determining the value of the flag
+          byte.  */
+       uint32_t flags = GDB_INDEX_SYMBOL_KIND_NONE;
+       switch (die->die_tag)
+       {
+         case DW_TAG_typedef:
+         case DW_TAG_base_type:
+         case DW_TAG_subrange_type:
+           GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE);
+           GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1);
+           break;
+         case DW_TAG_enumerator:
+           GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
+                                           GDB_INDEX_SYMBOL_KIND_VARIABLE);
+           if (!is_cxx () && !is_java ())
+             GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1);
+           break;
+         case DW_TAG_subprogram:
+           GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
+                                           GDB_INDEX_SYMBOL_KIND_FUNCTION);
+           if (!is_ada ())
+             GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static);
+           break;
+         case DW_TAG_constant:
+           GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
+                                           GDB_INDEX_SYMBOL_KIND_VARIABLE);
+           GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static);
+           break;
+         case DW_TAG_variable:
+           GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
+                                           GDB_INDEX_SYMBOL_KIND_VARIABLE);
+           GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static);
+           break;
+         case DW_TAG_namespace:
+         case DW_TAG_imported_declaration:
+           GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE);
+           break;
+         case DW_TAG_class_type:
+         case DW_TAG_interface_type:
+         case DW_TAG_structure_type:
+         case DW_TAG_union_type:
+         case DW_TAG_enumeration_type:
+           GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE);
+           if (!is_cxx () && !is_java ())
+           GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1);
+           break;
+         default:
+           /* An unusual tag.  Leave the flag-byte empty.  */
+           break;
+       }
+       dw2_asm_output_data (1, flags >> GDB_INDEX_CU_BITSIZE,
+                            "GDB-index flags");
+     }
+   dw2_asm_output_nstring (entry->name, -1, "external name");
+ }
  /* Output the public names table used to speed up access to externally
     visible names; or the public types table used to find type definitions.  */
  
@@@ -9288,23 -9248,14 +9380,14 @@@ output_pubnames (vec<pubname_entry, va_
    unsigned long pubnames_length = size_of_pubnames (names);
    pubname_ref pub;
  
-   if (!want_pubnames () || !info_section_emitted)
-     return;
-   if (names == pubname_table)
-     switch_to_section (debug_pubnames_section);
-   else
-     switch_to_section (debug_pubtypes_section);
    if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
      dw2_asm_output_data (4, 0xffffffff,
        "Initial length escape value indicating 64-bit DWARF extension");
-   if (names == pubname_table)
-     dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
-                        "Length of Public Names Info");
-   else
-     dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
-                        "Length of Public Type Names Info");
-   /* Version number for pubnames/pubtypes is still 2, even in DWARF3.  */
+   dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, "Pub Info Length");
+   /* Version number for pubnames/pubtypes is independent of dwarf version.  */
    dw2_asm_output_data (2, 2, "DWARF Version");
    if (dwarf_split_debug_info)
      dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
                             debug_skeleton_info_section,
                              : 0);
            }
  
-         dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset");
-         dw2_asm_output_nstring (pub->name, -1, "external name");
+           output_pubname (die_offset, pub);
        }
      }
  
    dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL);
  }
  
+ /* Output public names and types tables if necessary.  */
+ static void
+ output_pubtables (void)
+ {
+   if (!want_pubnames () || !info_section_emitted)
+     return;
+   switch_to_section (debug_pubnames_section);
+   output_pubnames (pubname_table);
+   /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2.
+      It shouldn't hurt to emit it always, since pure DWARF2 consumers
+      simply won't look for the section.  */
+   switch_to_section (debug_pubtypes_section);
+   output_pubnames (pubtype_table);
+ }
  /* Output the information that goes into the .debug_aranges table.
     Namely, define the beginning and ending address range of the
     text section generated for this compilation unit.  */
@@@ -10295,25 -10262,25 +10394,25 @@@ simple_type_size_in_bits (const_tree ty
      return BITS_PER_WORD;
    else if (TYPE_SIZE (type) == NULL_TREE)
      return 0;
 -  else if (host_integerp (TYPE_SIZE (type), 1))
 -    return tree_low_cst (TYPE_SIZE (type), 1);
 +  else if (tree_fits_uhwi_p (TYPE_SIZE (type)))
 +    return tree_to_uhwi (TYPE_SIZE (type));
    else
      return TYPE_ALIGN (type);
  }
  
 -/* Similarly, but return a double_int instead of UHWI.  */
 +/* Similarly, but return a wide_int instead of UHWI.  */
  
 -static inline double_int
 -double_int_type_size_in_bits (const_tree type)
 +static inline offset_int
 +wide_int_type_size_in_bits (const_tree type)
  {
    if (TREE_CODE (type) == ERROR_MARK)
 -    return double_int::from_uhwi (BITS_PER_WORD);
 +    return BITS_PER_WORD;
    else if (TYPE_SIZE (type) == NULL_TREE)
 -    return double_int_zero;
 +    return 0;
    else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
 -    return tree_to_double_int (TYPE_SIZE (type));
 +    return wi::to_offset (TYPE_SIZE (type));
    else
 -    return double_int::from_uhwi (TYPE_ALIGN (type));
 +    return TYPE_ALIGN (type);
  }
  
  /*  Given a pointer to a tree node for a subrange type, return a pointer
@@@ -11800,7 -11767,9 +11899,7 @@@ clz_loc_descriptor (rtx rtl, enum machi
    rtx msb;
  
    if (GET_MODE_CLASS (mode) != MODE_INT
 -      || GET_MODE (XEXP (rtl, 0)) != mode
 -      || (GET_CODE (rtl) == CLZ
 -        && GET_MODE_BITSIZE (mode) > HOST_BITS_PER_DOUBLE_INT))
 +      || GET_MODE (XEXP (rtl, 0)) != mode)
      return NULL;
  
    op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
      msb = GEN_INT ((unsigned HOST_WIDE_INT) 1
                   << (GET_MODE_BITSIZE (mode) - 1));
    else
 -    msb = immed_double_const (0, (unsigned HOST_WIDE_INT) 1
 -                                << (GET_MODE_BITSIZE (mode)
 -                                    - HOST_BITS_PER_WIDE_INT - 1), mode);
 +    msb = immed_wide_int_const 
 +      (wi::set_bit_in_zero (GET_MODE_PRECISION (mode) - 1,
 +                          GET_MODE_PRECISION (mode)), mode);
    if (GET_CODE (msb) == CONST_INT && INTVAL (msb) < 0)
      tmp = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32
                         ? DW_OP_const4u : HOST_BITS_PER_WIDE_INT == 64
@@@ -12788,16 -12757,7 +12887,16 @@@ mem_loc_descriptor (rtx rtl, enum machi
          mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
          mem_loc_result->dw_loc_oprnd1.v.val_die_ref.die = type_die;
          mem_loc_result->dw_loc_oprnd1.v.val_die_ref.external = 0;
 -        if (SCALAR_FLOAT_MODE_P (mode))
 +#if TARGET_SUPPORTS_WIDE_INT == 0
 +        if (!SCALAR_FLOAT_MODE_P (mode))
 +          {
 +            mem_loc_result->dw_loc_oprnd2.val_class
 +              = dw_val_class_const_double;
 +            mem_loc_result->dw_loc_oprnd2.v.val_double
 +              = rtx_to_double_int (rtl);
 +          }
 +        else
 +#endif
            {
              unsigned int length = GET_MODE_SIZE (mode);
              unsigned char *array
              mem_loc_result->dw_loc_oprnd2.v.val_vec.elt_size = 4;
              mem_loc_result->dw_loc_oprnd2.v.val_vec.array = array;
            }
 -        else
 -          {
 -            mem_loc_result->dw_loc_oprnd2.val_class
 -              = dw_val_class_const_double;
 -            mem_loc_result->dw_loc_oprnd2.v.val_double
 -              = rtx_to_double_int (rtl);
 -          }
 +      }
 +      break;
 +
 +    case CONST_WIDE_INT:
 +      if (!dwarf_strict)
 +      {
 +        dw_die_ref type_die;
 +
 +        type_die = base_type_for_mode (mode,
 +                                       GET_MODE_CLASS (mode) == MODE_INT);
 +        if (type_die == NULL)
 +          return NULL;
 +        mem_loc_result = new_loc_descr (DW_OP_GNU_const_type, 0, 0);
 +        mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
 +        mem_loc_result->dw_loc_oprnd1.v.val_die_ref.die = type_die;
 +        mem_loc_result->dw_loc_oprnd1.v.val_die_ref.external = 0;
 +        mem_loc_result->dw_loc_oprnd2.val_class
 +          = dw_val_class_wide_int;
 +        mem_loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc_cleared_wide_int ();
 +        *mem_loc_result->dw_loc_oprnd2.v.val_wide = std::make_pair (rtl, mode);
        }
        break;
  
@@@ -13299,15 -13246,7 +13398,15 @@@ loc_descriptor (rtx rtl, enum machine_m
             adequately represented.  We output CONST_DOUBLEs as blocks.  */
          loc_result = new_loc_descr (DW_OP_implicit_value,
                                      GET_MODE_SIZE (mode), 0);
 -        if (SCALAR_FLOAT_MODE_P (mode))
 +#if TARGET_SUPPORTS_WIDE_INT == 0
 +        if (!SCALAR_FLOAT_MODE_P (mode))
 +          {
 +            loc_result->dw_loc_oprnd2.val_class = dw_val_class_const_double;
 +            loc_result->dw_loc_oprnd2.v.val_double
 +              = rtx_to_double_int (rtl);
 +          }
 +        else
 +#endif
            {
              unsigned int length = GET_MODE_SIZE (mode);
              unsigned char *array
              loc_result->dw_loc_oprnd2.v.val_vec.elt_size = 4;
              loc_result->dw_loc_oprnd2.v.val_vec.array = array;
            }
 -        else
 -          {
 -            loc_result->dw_loc_oprnd2.val_class = dw_val_class_const_double;
 -            loc_result->dw_loc_oprnd2.v.val_double
 -              = rtx_to_double_int (rtl);
 -          }
 +      }
 +      break;
 +
 +    case CONST_WIDE_INT:
 +      if (mode == VOIDmode)
 +      mode = GET_MODE (rtl);
 +
 +      if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
 +      {
 +        gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl));
 +
 +        /* Note that a CONST_DOUBLE rtx could represent either an integer
 +           or a floating-point constant.  A CONST_DOUBLE is used whenever
 +           the constant requires more than one word in order to be
 +           adequately represented.  We output CONST_DOUBLEs as blocks.  */
 +        loc_result = new_loc_descr (DW_OP_implicit_value,
 +                                    GET_MODE_SIZE (mode), 0);
 +        loc_result->dw_loc_oprnd2.val_class = dw_val_class_wide_int;
 +        loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc_cleared_wide_int ();
 +        *loc_result->dw_loc_oprnd2.v.val_wide = std::make_pair (rtl, mode);
        }
        break;
  
            ggc_alloc_atomic (length * elt_size);
          unsigned int i;
          unsigned char *p;
 +        enum machine_mode imode = GET_MODE_INNER (mode);
  
          gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl));
          switch (GET_MODE_CLASS (mode))
              for (i = 0, p = array; i < length; i++, p += elt_size)
                {
                  rtx elt = CONST_VECTOR_ELT (rtl, i);
 -                double_int val = rtx_to_double_int (elt);
 -
 -                if (elt_size <= sizeof (HOST_WIDE_INT))
 -                  insert_int (val.to_shwi (), elt_size, p);
 -                else
 -                  {
 -                    gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
 -                    insert_double (val, p);
 -                  }
 +                insert_wide_int (std::make_pair (elt, imode), p);
                }
              break;
  
@@@ -13609,10 -13541,10 +13708,10 @@@ dw_sra_loc_expr (tree decl, rtx loc
    enum var_init_status initialized;
  
    if (DECL_SIZE (decl) == NULL
 -      || !host_integerp (DECL_SIZE (decl), 1))
 +      || !tree_fits_uhwi_p (DECL_SIZE (decl)))
      return NULL;
  
 -  decl_size = tree_low_cst (DECL_SIZE (decl), 1);
 +  decl_size = tree_to_uhwi (DECL_SIZE (decl));
    descr = NULL;
    descr_tail = &descr;
  
@@@ -14315,17 -14247,17 +14414,17 @@@ loc_list_from_tree (tree loc, int want_
        }
  
      case INTEGER_CST:
 -      if ((want_address || !host_integerp (loc, 0))
 +      if ((want_address || !tree_fits_shwi_p (loc))
          && (ret = cst_pool_loc_descr (loc)))
        have_address = 1;
        else if (want_address == 2
 -             && host_integerp (loc, 0)
 +             && tree_fits_shwi_p (loc)
               && (ret = address_of_int_loc_descriptor
                           (int_size_in_bytes (TREE_TYPE (loc)),
 -                          tree_low_cst (loc, 0))))
 +                          tree_to_shwi (loc))))
        have_address = 1;
 -      else if (host_integerp (loc, 0))
 -      ret = int_loc_descriptor (tree_low_cst (loc, 0));
 +      else if (tree_fits_shwi_p (loc))
 +      ret = int_loc_descriptor (tree_to_shwi (loc));
        else
        {
          expansion_failed (loc, NULL_RTX,
  
      case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
 -      if (host_integerp (TREE_OPERAND (loc, 1), 0))
 +      if (tree_fits_shwi_p (TREE_OPERAND (loc, 1)))
        {
          list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
          if (list_ret == 0)
            return 0;
  
 -        loc_list_plus_const (list_ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
 +        loc_list_plus_const (list_ret, tree_to_shwi (TREE_OPERAND (loc, 1)));
          break;
        }
  
@@@ -14685,12 -14617,14 +14784,12 @@@ simple_decl_align_in_bits (const_tree d
  
  /* Return the result of rounding T up to ALIGN.  */
  
 -static inline double_int
 -round_up_to_align (double_int t, unsigned int align)
 +static inline offset_int
 +round_up_to_align (offset_int t, unsigned int align)
  {
 -  double_int alignd = double_int::from_uhwi (align);
 -  t += alignd;
 -  t += double_int_minus_one;
 -  t = t.div (alignd, true, TRUNC_DIV_EXPR);
 -  t *= alignd;
 +  t += align - 1;
 +  t = wi::udiv_trunc (t, align);
 +  t *= align;
    return t;
  }
  
  static HOST_WIDE_INT
  field_byte_offset (const_tree decl)
  {
 -  double_int object_offset_in_bits;
 -  double_int object_offset_in_bytes;
 -  double_int bitpos_int;
 +  offset_int object_offset_in_bits;
 +  offset_int object_offset_in_bytes;
 +  offset_int bitpos_int;
  
    if (TREE_CODE (decl) == ERROR_MARK)
      return 0;
    if (TREE_CODE (bit_position (decl)) != INTEGER_CST)
      return 0;
  
 -  bitpos_int = tree_to_double_int (bit_position (decl));
 +  bitpos_int = wi::to_offset (bit_position (decl));
  
  #ifdef PCC_BITFIELD_TYPE_MATTERS
    if (PCC_BITFIELD_TYPE_MATTERS)
      {
        tree type;
        tree field_size_tree;
 -      double_int deepest_bitpos;
 -      double_int field_size_in_bits;
 +      offset_int deepest_bitpos;
 +      offset_int field_size_in_bits;
        unsigned int type_align_in_bits;
        unsigned int decl_align_in_bits;
 -      double_int type_size_in_bits;
 +      offset_int type_size_in_bits;
  
        type = field_type (decl);
 -      type_size_in_bits = double_int_type_size_in_bits (type);
 +      type_size_in_bits = wide_int_type_size_in_bits (type);
        type_align_in_bits = simple_type_align_in_bits (type);
  
        field_size_tree = DECL_SIZE (decl);
  
        /* If the size of the field is not constant, use the type size.  */
        if (TREE_CODE (field_size_tree) == INTEGER_CST)
 -      field_size_in_bits = tree_to_double_int (field_size_tree);
 +      field_size_in_bits = wi::to_offset (field_size_tree);
        else
        field_size_in_bits = type_size_in_bits;
  
        object_offset_in_bits
        = round_up_to_align (object_offset_in_bits, type_align_in_bits);
  
 -      if (object_offset_in_bits.ugt (bitpos_int))
 +      if (wi::gtu_p (object_offset_in_bits, bitpos_int))
        {
          object_offset_in_bits = deepest_bitpos - type_size_in_bits;
  
      object_offset_in_bits = bitpos_int;
  
    object_offset_in_bytes
 -    = object_offset_in_bits.div (double_int::from_uhwi (BITS_PER_UNIT),
 -                               true, TRUNC_DIV_EXPR);
 +    = wi::udiv_trunc (object_offset_in_bits, BITS_PER_UNIT);
    return object_offset_in_bytes.to_shwi ();
  }
  \f
@@@ -14921,7 -14856,7 +15020,7 @@@ add_data_member_location_attribute (dw_
          add_loc_descr (&loc_descr, tmp);
  
          /* Calculate the address of the offset.  */
 -        offset = tree_low_cst (BINFO_VPTR_FIELD (decl), 0);
 +        offset = tree_to_shwi (BINFO_VPTR_FIELD (decl));
          gcc_assert (offset < 0);
  
          tmp = int_loc_descriptor (-offset);
          add_loc_descr (&loc_descr, tmp);
        }
        else
 -      offset = tree_low_cst (BINFO_OFFSET (decl), 0);
 +      offset = tree_to_shwi (BINFO_OFFSET (decl));
      }
    else
      offset = field_byte_offset (decl);
@@@ -14999,27 -14934,22 +15098,27 @@@ extract_int (const unsigned char *src, 
    return val;
  }
  
 -/* Writes double_int values to dw_vec_const array.  */
 +/* Writes wide_int values to dw_vec_const array.  */
  
  static void
 -insert_double (double_int val, unsigned char *dest)
 +insert_wide_int (const wide_int &val, unsigned char *dest)
  {
 -  unsigned char *p0 = dest;
 -  unsigned char *p1 = dest + sizeof (HOST_WIDE_INT);
 +  int i;
  
    if (WORDS_BIG_ENDIAN)
 -    {
 -      p0 = p1;
 -      p1 = dest;
 -    }
 -
 -  insert_int ((HOST_WIDE_INT) val.low, sizeof (HOST_WIDE_INT), p0);
 -  insert_int ((HOST_WIDE_INT) val.high, sizeof (HOST_WIDE_INT), p1);
 +    for (i = (int)get_full_len (val) - 1; i >= 0; i--)
 +      {
 +      insert_int ((HOST_WIDE_INT) val.elt (i), 
 +                  sizeof (HOST_WIDE_INT), dest);
 +      dest += sizeof (HOST_WIDE_INT);
 +      }
 +  else
 +    for (i = 0; i < (int)get_full_len (val); i++)
 +      {
 +      insert_int ((HOST_WIDE_INT) val.elt (i), 
 +                  sizeof (HOST_WIDE_INT), dest);
 +      dest += sizeof (HOST_WIDE_INT);
 +      }
  }
  
  /* Writes floating point values to dw_vec_const array.  */
@@@ -15064,11 -14994,6 +15163,11 @@@ add_const_value_attribute (dw_die_ref d
        }
        return true;
  
 +    case CONST_WIDE_INT:
 +      add_AT_wide (die, DW_AT_const_value, 
 +                 std::make_pair (rtl, GET_MODE (rtl)));
 +      return true;
 +
      case CONST_DOUBLE:
        /* Note that a CONST_DOUBLE rtx could represent either an integer or a
         floating-point constant.  A CONST_DOUBLE is used whenever the
        {
        enum machine_mode mode = GET_MODE (rtl);
  
 -      if (SCALAR_FLOAT_MODE_P (mode))
 +      if (TARGET_SUPPORTS_WIDE_INT == 0 && !SCALAR_FLOAT_MODE_P (mode))
 +        add_AT_double (die, DW_AT_const_value,
 +                       CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
 +      else
          {
            unsigned int length = GET_MODE_SIZE (mode);
            unsigned char *array = (unsigned char *) ggc_alloc_atomic (length);
            insert_float (rtl, array);
            add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
          }
 -      else
 -        add_AT_double (die, DW_AT_const_value,
 -                       CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
        }
        return true;
  
          (length * elt_size);
        unsigned int i;
        unsigned char *p;
 +      enum machine_mode imode = GET_MODE_INNER (mode);
  
        switch (GET_MODE_CLASS (mode))
          {
            for (i = 0, p = array; i < length; i++, p += elt_size)
              {
                rtx elt = CONST_VECTOR_ELT (rtl, i);
 -              double_int val = rtx_to_double_int (elt);
 -
 -              if (elt_size <= sizeof (HOST_WIDE_INT))
 -                insert_int (val.to_shwi (), elt_size, p);
 -              else
 -                {
 -                  gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
 -                  insert_double (val, p);
 -                }
 +              insert_wide_int (std::make_pair (elt, imode), p);
              }
            break;
  
@@@ -15211,7 -15143,7 +15310,7 @@@ reference_to_unused (tree * tp, int * w
    else if (TREE_CODE (*tp) == VAR_DECL)
      {
        struct varpool_node *node = varpool_get_node (*tp);
-       if (!node || !node->symbol.definition)
+       if (!node || !node->definition)
        return *tp;
      }
    else if (TREE_CODE (*tp) == FUNCTION_DECL
@@@ -15595,9 -15527,9 +15694,9 @@@ fortran_common (tree decl, HOST_WIDE_IN
    *value = 0;
    if (offset != NULL)
      {
 -      if (!host_integerp (offset, 0))
 +      if (!tree_fits_shwi_p (offset))
        return NULL_TREE;
 -      *value = tree_low_cst (offset, 0);
 +      *value = tree_to_shwi (offset);
      }
    if (bitpos != 0)
      *value += bitpos / BITS_PER_UNIT;
@@@ -15763,14 -15695,14 +15862,14 @@@ native_encode_initializer (tree init, u
          constructor_elt *ce;
  
          if (TYPE_DOMAIN (type) == NULL_TREE
 -            || !host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0))
 +            || !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
            return false;
  
          fieldsize = int_size_in_bytes (TREE_TYPE (type));
          if (fieldsize <= 0)
            return false;
  
 -        min_index = tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0);
 +        min_index = tree_to_shwi (TYPE_MIN_VALUE (TYPE_DOMAIN (type)));
          memset (array, '\0', size);
          FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
            {
              tree index = ce->index;
              int pos = curpos;
              if (index && TREE_CODE (index) == RANGE_EXPR)
 -              pos = (tree_low_cst (TREE_OPERAND (index, 0), 0) - min_index)
 +              pos = (tree_to_shwi (TREE_OPERAND (index, 0)) - min_index)
                      * fieldsize;
              else if (index)
 -              pos = (tree_low_cst (index, 0) - min_index) * fieldsize;
 +              pos = (tree_to_shwi (index) - min_index) * fieldsize;
  
              if (val)
                {
              curpos = pos + fieldsize;
              if (index && TREE_CODE (index) == RANGE_EXPR)
                {
 -                int count = tree_low_cst (TREE_OPERAND (index, 1), 0)
 -                            - tree_low_cst (TREE_OPERAND (index, 0), 0);
 +                int count = tree_to_shwi (TREE_OPERAND (index, 1))
 +                            - tree_to_shwi (TREE_OPERAND (index, 0));
                  while (count-- > 0)
                    {
                      if (val)
                  && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
                return false;
              else if (DECL_SIZE_UNIT (field) == NULL_TREE
 -                     || !host_integerp (DECL_SIZE_UNIT (field), 0))
 +                     || !tree_fits_shwi_p (DECL_SIZE_UNIT (field)))
                return false;
 -            fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 0);
 +            fieldsize = tree_to_shwi (DECL_SIZE_UNIT (field));
              pos = int_byte_position (field);
              gcc_assert (pos + fieldsize <= size);
              if (val
@@@ -16229,9 -16161,9 +16328,9 @@@ add_bound_info (dw_die_ref subrange_die
  
        /* Use the default if possible.  */
        if (bound_attr == DW_AT_lower_bound
 -          && host_integerp (bound, 0)
 +          && tree_fits_shwi_p (bound)
            && (dflt = lower_bound_default ()) != -1
 -          && tree_low_cst (bound, 0) == dflt)
 +          && tree_to_shwi (bound) == dflt)
          ;
  
        /* Otherwise represent the bound as an unsigned value with the
           type will be necessary to re-interpret it unambiguously.  */
        else if (prec < HOST_BITS_PER_WIDE_INT)
          {
 -          unsigned HOST_WIDE_INT mask
 -            = ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
            add_AT_unsigned (subrange_die, bound_attr,
 -                           TREE_INT_CST_LOW (bound) & mask);
 +                           zext_hwi (tree_to_hwi (bound), prec));
          }
 -      else if (prec == HOST_BITS_PER_WIDE_INT
 -               || TREE_INT_CST_HIGH (bound) == 0)
 -        add_AT_unsigned (subrange_die, bound_attr,
 -                         TREE_INT_CST_LOW (bound));
 +      else if (prec == HOST_BITS_PER_WIDE_INT 
 +               || (cst_fits_uhwi_p (bound) && wi::ges_p (bound, 0)))
 +        add_AT_unsigned (subrange_die, bound_attr, tree_to_hwi (bound));
        else
 -        add_AT_double (subrange_die, bound_attr, TREE_INT_CST_HIGH (bound),
 -                       TREE_INT_CST_LOW (bound));
 +        add_AT_wide (subrange_die, bound_attr, wide_int (bound));
        }
        break;
  
@@@ -16456,8 -16392,8 +16555,8 @@@ add_bit_offset_attribute (dw_die_ref di
    /* We can't yet handle bit-fields whose offsets are variable, so if we
       encounter such things, just return without generating any attribute
       whatsoever.  Likewise for variable or too large size.  */
 -  if (! host_integerp (bit_position (decl), 0)
 -      || ! host_integerp (DECL_SIZE (decl), 1))
 +  if (! tree_fits_shwi_p (bit_position (decl))
 +      || ! tree_fits_uhwi_p (DECL_SIZE (decl)))
      return;
  
    bitpos_int = int_bit_position (decl);
  
    if (! BYTES_BIG_ENDIAN)
      {
 -      highest_order_field_bit_offset += tree_low_cst (DECL_SIZE (decl), 0);
 +      highest_order_field_bit_offset += tree_to_shwi (DECL_SIZE (decl));
        highest_order_object_bit_offset += simple_type_size_in_bits (type);
      }
  
@@@ -16497,8 -16433,8 +16596,8 @@@ add_bit_size_attribute (dw_die_ref die
    gcc_assert (TREE_CODE (decl) == FIELD_DECL
              && DECL_BIT_FIELD_TYPE (decl));
  
 -  if (host_integerp (DECL_SIZE (decl), 1))
 -    add_AT_unsigned (die, DW_AT_bit_size, tree_low_cst (DECL_SIZE (decl), 1));
 +  if (tree_fits_uhwi_p (DECL_SIZE (decl)))
 +    add_AT_unsigned (die, DW_AT_bit_size, tree_to_uhwi (DECL_SIZE (decl)));
  }
  
  /* If the compiled language is ANSI C, then add a 'prototyped'
@@@ -16567,10 -16503,10 +16666,10 @@@ add_pure_or_virtual_attribute (dw_die_r
      {
        add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
  
 -      if (host_integerp (DECL_VINDEX (func_decl), 0))
 +      if (tree_fits_shwi_p (DECL_VINDEX (func_decl)))
        add_AT_loc (die, DW_AT_vtable_elem_location,
                    new_loc_descr (DW_OP_constu,
 -                                 tree_low_cst (DECL_VINDEX (func_decl), 0),
 +                                 tree_to_shwi (DECL_VINDEX (func_decl)),
                                   0));
  
        /* GNU extension: Record what type this method came from originally.  */
@@@ -17117,8 -17053,8 +17216,8 @@@ descr_info_loc (tree val, tree base_dec
      case VAR_DECL:
        return loc_descriptor_from_tree (val, 0);
      case INTEGER_CST:
 -      if (host_integerp (val, 0))
 -      return int_loc_descriptor (tree_low_cst (val, 0));
 +      if (tree_fits_shwi_p (val))
 +      return int_loc_descriptor (tree_to_shwi (val));
        break;
      case INDIRECT_REF:
        size = int_size_in_bytes (TREE_TYPE (val));
        return loc;
      case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
 -      if (host_integerp (TREE_OPERAND (val, 1), 1)
 -        && (unsigned HOST_WIDE_INT) tree_low_cst (TREE_OPERAND (val, 1), 1)
 +      if (tree_fits_uhwi_p (TREE_OPERAND (val, 1))
 +        && (unsigned HOST_WIDE_INT) tree_to_uhwi (TREE_OPERAND (val, 1))
             < 16384)
        {
          loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
          if (!loc)
            break;
 -        loc_descr_plus_const (&loc, tree_low_cst (TREE_OPERAND (val, 1), 0));
 +        loc_descr_plus_const (&loc, tree_to_shwi (TREE_OPERAND (val, 1)));
        }
        else
        {
@@@ -17181,9 -17117,9 +17280,9 @@@ add_descr_info_field (dw_die_ref die, e
  {
    dw_loc_descr_ref loc;
  
 -  if (host_integerp (val, 0))
 +  if (tree_fits_shwi_p (val))
      {
 -      add_AT_unsigned (die, attr, tree_low_cst (val, 0));
 +      add_AT_unsigned (die, attr, tree_to_shwi (val));
        return;
      }
  
@@@ -17234,9 -17170,9 +17333,9 @@@ gen_descr_array_type_die (tree type, st
          /* If it is the default value, omit it.  */
          int dflt;
  
 -        if (host_integerp (info->dimen[dim].lower_bound, 0)
 +        if (tree_fits_shwi_p (info->dimen[dim].lower_bound)
              && (dflt = lower_bound_default ()) != -1
 -            && tree_low_cst (info->dimen[dim].lower_bound, 0) == dflt)
 +            && tree_to_shwi (info->dimen[dim].lower_bound) == dflt)
            ;
          else
            add_descr_info_field (subrange_die, DW_AT_lower_bound,
@@@ -17383,9 -17319,9 +17482,9 @@@ gen_enumeration_type_die (tree type, dw
          if (TREE_CODE (value) == CONST_DECL)
            value = DECL_INITIAL (value);
  
 -        if (host_integerp (value, TYPE_UNSIGNED (TREE_TYPE (value)))
 +        if (tree_fits_hwi_p (value)
              && (simple_type_size_in_bits (TREE_TYPE (value))
 -                <= HOST_BITS_PER_WIDE_INT || host_integerp (value, 0)))
 +                <= HOST_BITS_PER_WIDE_INT || tree_fits_shwi_p (value)))
            /* DWARF2 does not provide a way of indicating whether or
               not enumeration constants are signed or unsigned.  GDB
               always assumes the values are signed, so we output all
               This should be re-worked to use correct signed/unsigned
               int/double tags for all cases, instead of always treating as
               signed.  */
 -          add_AT_int (enum_die, DW_AT_const_value, TREE_INT_CST_LOW (value));
 +          add_AT_int (enum_die, DW_AT_const_value, tree_to_hwi (value));
          else
            /* Enumeration constants may be wider than HOST_WIDE_INT.  Handle
               that here.  */
 -          add_AT_double (enum_die, DW_AT_const_value,
 -                         TREE_INT_CST_HIGH (value), TREE_INT_CST_LOW (value));
 +          add_AT_wide (enum_die, DW_AT_const_value, wide_int (value));
        }
  
        add_gnat_descriptive_type_attribute (type_die, type, context_die);
@@@ -17884,7 -17821,7 +17983,7 @@@ premark_types_used_by_global_vars_helpe
        /* Ask cgraph if the global variable really is to be emitted.
           If yes, then we'll keep the DIE of ENTRY->TYPE.  */
        struct varpool_node *node = varpool_get_node (entry->var_decl);
-       if (node && node->symbol.definition)
+       if (node && node->definition)
        {
          die->die_perennial_p = 1;
          /* Keep the parent DIEs as well.  */
@@@ -23174,9 -23111,9 +23273,9 @@@ optimize_location_into_implicit_ptr (dw
       we can add DW_OP_GNU_implicit_pointer.  */
    STRIP_NOPS (init);
    if (TREE_CODE (init) == POINTER_PLUS_EXPR
 -      && host_integerp (TREE_OPERAND (init, 1), 0))
 +      && tree_fits_shwi_p (TREE_OPERAND (init, 1)))
      {
 -      offset = tree_low_cst (TREE_OPERAND (init, 1), 0);
 +      offset = tree_to_shwi (TREE_OPERAND (init, 1));
        init = TREE_OPERAND (init, 0);
        STRIP_NOPS (init);
      }
@@@ -23464,9 -23401,6 +23563,9 @@@ hash_loc_operands (dw_loc_descr_ref loc
          hash = iterative_hash_object (val2->v.val_double.low, hash);
          hash = iterative_hash_object (val2->v.val_double.high, hash);
          break;
 +      case dw_val_class_wide_int:
 +        hash = iterative_hash_object (*val2->v.val_wide, hash);
 +        break;
        case dw_val_class_addr:
          hash = iterative_hash_rtx (val2->v.val_addr, hash);
          break;
            hash = iterative_hash_object (val2->v.val_double.low, hash);
            hash = iterative_hash_object (val2->v.val_double.high, hash);
            break;
 +        case dw_val_class_wide_int:
 +          hash = iterative_hash_object (*val2->v.val_wide, hash);
 +          break;
          default:
            gcc_unreachable ();
          }
@@@ -23707,8 -23638,6 +23806,8 @@@ compare_loc_operands (dw_loc_descr_ref 
        case dw_val_class_const_double:
          return valx2->v.val_double.low == valy2->v.val_double.low
                 && valx2->v.val_double.high == valy2->v.val_double.high;
 +      case dw_val_class_wide_int:
 +        return *valx2->v.val_wide == *valy2->v.val_wide;
        case dw_val_class_addr:
          return rtx_equal_p (valx2->v.val_addr, valy2->v.val_addr);
        default:
        case dw_val_class_const_double:
          return valx2->v.val_double.low == valy2->v.val_double.low
                 && valx2->v.val_double.high == valy2->v.val_double.high;
 +      case dw_val_class_wide_int:
 +        return *valx2->v.val_wide == *valy2->v.val_wide;
        default:
          gcc_unreachable ();
        }
@@@ -24264,12 -24191,7 +24363,7 @@@ dwarf2out_finish (const char *filename
        output_location_lists (comp_unit_die ());
      }
  
-   /* Output public names and types tables if necessary.  */
-   output_pubnames (pubname_table);
-   /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2.
-      It shouldn't hurt to emit it always, since pure DWARF2 consumers
-      simply won't look for the section.  */
-   output_pubnames (pubtype_table);
+   output_pubtables ();
  
    /* Output the address range information if a CU (.debug_info section)
       was emitted.  We output an empty table even if we had no functions
diff --combined gcc/except.c
index a3076056aea480a27dd6ee9551d999ce9367a0f4,a52d317ddae9fc53dca795a2a07c3c06bcf11572..937935f03b6ac9402066cd5c586353da2a70aec4
@@@ -139,7 -139,7 +139,7 @@@ along with GCC; see the file COPYING3
  #include "diagnostic.h"
  #include "tree-pretty-print.h"
  #include "tree-pass.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
  #include "cfgloop.h"
  
  /* Provide defaults for stuff that may not be defined when using
@@@ -313,20 -313,20 +313,20 @@@ init_eh (void
        /* Cache the interesting field offsets so that we have
         easy access from rtl.  */
        sjlj_fc_call_site_ofs
 -      = (tree_low_cst (DECL_FIELD_OFFSET (f_cs), 1)
 -         + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_cs), 1) / BITS_PER_UNIT);
 +      = (tree_to_uhwi (DECL_FIELD_OFFSET (f_cs))
 +         + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_cs)) / BITS_PER_UNIT);
        sjlj_fc_data_ofs
 -      = (tree_low_cst (DECL_FIELD_OFFSET (f_data), 1)
 -         + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_data), 1) / BITS_PER_UNIT);
 +      = (tree_to_uhwi (DECL_FIELD_OFFSET (f_data))
 +         + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_data)) / BITS_PER_UNIT);
        sjlj_fc_personality_ofs
 -      = (tree_low_cst (DECL_FIELD_OFFSET (f_per), 1)
 -         + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_per), 1) / BITS_PER_UNIT);
 +      = (tree_to_uhwi (DECL_FIELD_OFFSET (f_per))
 +         + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_per)) / BITS_PER_UNIT);
        sjlj_fc_lsda_ofs
 -      = (tree_low_cst (DECL_FIELD_OFFSET (f_lsda), 1)
 -         + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_lsda), 1) / BITS_PER_UNIT);
 +      = (tree_to_uhwi (DECL_FIELD_OFFSET (f_lsda))
 +         + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_lsda)) / BITS_PER_UNIT);
        sjlj_fc_jbuf_ofs
 -      = (tree_low_cst (DECL_FIELD_OFFSET (f_jbuf), 1)
 -         + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_jbuf), 1) / BITS_PER_UNIT);
 +      = (tree_to_uhwi (DECL_FIELD_OFFSET (f_jbuf))
 +         + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_jbuf)) / BITS_PER_UNIT);
      }
  }
  
@@@ -2050,8 -2050,8 +2050,8 @@@ expand_builtin_eh_common (tree region_n
    HOST_WIDE_INT region_nr;
    eh_region region;
  
 -  gcc_assert (host_integerp (region_nr_t, 0));
 -  region_nr = tree_low_cst (region_nr_t, 0);
 +  gcc_assert (tree_fits_shwi_p (region_nr_t));
 +  region_nr = tree_to_shwi (region_nr_t);
  
    region = (*cfun->eh->region_array)[region_nr];
  
@@@ -2145,7 -2145,7 +2145,7 @@@ expand_builtin_eh_return_data_regno (tr
        return constm1_rtx;
      }
  
 -  iwhich = tree_low_cst (which, 1);
 +  iwhich = tree_to_uhwi (which);
    iwhich = EH_RETURN_DATA_REGNO (iwhich);
    if (iwhich == INVALID_REGNUM)
      return constm1_rtx;
@@@ -2381,7 -2381,7 +2381,7 @@@ collect_one_action_chain (action_hash_t
              {
                /* Retrieve the filter from the head of the filter list
                   where we have stored it (see assign_filter_values).  */
 -              int filter = TREE_INT_CST_LOW (TREE_VALUE (c->filter_list));
 +              int filter = tree_to_hwi (TREE_VALUE (c->filter_list));
                next = add_action_record (ar_hash, filter, 0);
              }
            else
                flt_node = c->filter_list;
                for (; flt_node; flt_node = TREE_CHAIN (flt_node))
                  {
 -                  int filter = TREE_INT_CST_LOW (TREE_VALUE (flt_node));
 +                  int filter = tree_to_hwi (TREE_VALUE (flt_node));
                    next = add_action_record (ar_hash, filter, next);
                  }
              }
diff --combined gcc/expmed.c
index 90aa45e09e10b4812416300eb9e699a98cc7b254,59f81df5adff6038ad1f934b802b5b0439fe0d84..f7303c9eab4dd4a60351d2296174d93b14bbe883
@@@ -55,6 -55,7 +55,6 @@@ static void store_split_bit_field (rtx
  static rtx extract_fixed_bit_field (enum machine_mode, rtx,
                                    unsigned HOST_WIDE_INT,
                                    unsigned HOST_WIDE_INT, rtx, int);
 -static rtx mask_rtx (enum machine_mode, int, int, int);
  static rtx lshift_value (enum machine_mode, unsigned HOST_WIDE_INT, int);
  static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
                                    unsigned HOST_WIDE_INT, int);
@@@ -62,19 -63,6 +62,19 @@@ static void do_cmp_and_jump (rtx, rtx, 
  static rtx expand_smod_pow2 (enum machine_mode, rtx, HOST_WIDE_INT);
  static rtx expand_sdiv_pow2 (enum machine_mode, rtx, HOST_WIDE_INT);
  
 +/* Return a constant integer mask value of mode MODE with BITSIZE ones
 +   followed by BITPOS zeros, or the complement of that if COMPLEMENT.
 +   The mask is truncated if necessary to the width of mode MODE.  The
 +   mask is zero-extended if BITSIZE+BITPOS is too small for MODE.  */
 +
 +static inline rtx 
 +mask_rtx (enum machine_mode mode, int bitpos, int bitsize, bool complement)
 +{
 +  return immed_wide_int_const 
 +    (wi::shifted_mask (bitpos, bitsize, complement,
 +                     GET_MODE_PRECISION (mode)), mode);
 +}
 +
  /* Test whether a value is zero of a power of two.  */
  #define EXACT_POWER_OF_2_OR_ZERO_P(x) \
    (((x) & ((x) - (unsigned HOST_WIDE_INT) 1)) == 0)
@@@ -636,13 -624,28 +636,28 @@@ store_bit_field_1 (rtx str_rtx, unsigne
          || (bitsize % BITS_PER_WORD == 0 && bitnum % BITS_PER_WORD == 0)))
      {
        /* Use the subreg machinery either to narrow OP0 to the required
-        words or to cope with mode punning between equal-sized modes.  */
-       rtx sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0),
-                                    bitnum / BITS_PER_UNIT);
-       if (sub)
+        words or to cope with mode punning between equal-sized modes.
+        In the latter case, use subreg on the rhs side, not lhs.  */
+       rtx sub;
+       if (bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
+       {
+         sub = simplify_gen_subreg (GET_MODE (op0), value, fieldmode, 0);
+         if (sub)
+           {
+             emit_move_insn (op0, sub);
+             return true;
+           }
+       }
+       else
        {
-         emit_move_insn (sub, value);
-         return true;
+         sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0),
+                                    bitnum / BITS_PER_UNIT);
+         if (sub)
+           {
+             emit_move_insn (sub, value);
+             return true;
+           }
        }
      }
  
@@@ -1813,6 -1816,26 +1828,6 @@@ extract_fixed_bit_field (enum machine_m
    return expand_shift (RSHIFT_EXPR, mode, op0,
                       GET_MODE_BITSIZE (mode) - bitsize, target, 0);
  }
 -\f
 -/* Return a constant integer (CONST_INT or CONST_DOUBLE) mask value
 -   of mode MODE with BITSIZE ones followed by BITPOS zeros, or the
 -   complement of that if COMPLEMENT.  The mask is truncated if
 -   necessary to the width of mode MODE.  The mask is zero-extended if
 -   BITSIZE+BITPOS is too small for MODE.  */
 -
 -static rtx
 -mask_rtx (enum machine_mode mode, int bitpos, int bitsize, int complement)
 -{
 -  double_int mask;
 -
 -  mask = double_int::mask (bitsize);
 -  mask = mask.llshift (bitpos, HOST_BITS_PER_DOUBLE_INT);
 -
 -  if (complement)
 -    mask = ~mask;
 -
 -  return immed_double_int_const (mask, mode);
 -}
  
  /* Return a constant integer (CONST_INT or CONST_DOUBLE) rtx with the value
     VALUE << BITPOS.  */
@@@ -1821,7 -1844,12 +1836,7 @@@ static rt
  lshift_value (enum machine_mode mode, unsigned HOST_WIDE_INT value,
              int bitpos)
  {
 -  double_int val;
 -  
 -  val = double_int::from_uhwi (value);
 -  val = val.llshift (bitpos, HOST_BITS_PER_DOUBLE_INT);
 -
 -  return immed_double_int_const (val, mode);
 +  return immed_wide_int_const (wi::lshift (value, bitpos), mode);
  }
  \f
  /* Extract a bit field that is split across two words
@@@ -3049,40 -3077,37 +3064,40 @@@ expand_mult (enum machine_mode mode, rt
         only if the constant value exactly fits in an `unsigned int' without
         any truncation.  This means that multiplying by negative values does
         not work; results are off by 2^32 on a 32 bit machine.  */
 -
        if (CONST_INT_P (scalar_op1))
        {
          coeff = INTVAL (scalar_op1);
          is_neg = coeff < 0;
        }
 +#if TARGET_SUPPORTS_WIDE_INT
 +      else if (CONST_WIDE_INT_P (scalar_op1))
 +#else
        else if (CONST_DOUBLE_AS_INT_P (scalar_op1))
 +#endif
        {
 -        /* If we are multiplying in DImode, it may still be a win
 -           to try to work with shifts and adds.  */
 -        if (CONST_DOUBLE_HIGH (scalar_op1) == 0
 -            && (CONST_DOUBLE_LOW (scalar_op1) > 0
 -                || (CONST_DOUBLE_LOW (scalar_op1) < 0
 -                    && EXACT_POWER_OF_2_OR_ZERO_P
 -                         (CONST_DOUBLE_LOW (scalar_op1)))))
 +        int p = GET_MODE_PRECISION (mode);
 +        int shift = wi::exact_log2 (std::make_pair (scalar_op1, mode));
 +        /* Perfect power of 2.  */
 +        is_neg = false;
 +        if (shift > 0)
            {
 -            coeff = CONST_DOUBLE_LOW (scalar_op1);
 -            is_neg = false;
 +            /* Do the shift count trucation against the bitsize, not
 +               the precision.  See the comment above
 +               wide-int.c:trunc_shift for details.  */
 +            if (SHIFT_COUNT_TRUNCATED)
 +              shift &= GET_MODE_BITSIZE (mode) - 1;
 +            /* We could consider adding just a move of 0 to target
 +               if the shift >= p  */
 +            if (shift < p)
 +              return expand_shift (LSHIFT_EXPR, mode, op0, 
 +                                   shift, target, unsignedp);
 +            /* Any positive number that fits in a word.  */
 +            coeff = CONST_WIDE_INT_ELT (scalar_op1, 0);
            }
 -        else if (CONST_DOUBLE_LOW (scalar_op1) == 0)
 +        else if (wi::sign_mask (std::make_pair (scalar_op1, mode)) == 0)
            {
 -            coeff = CONST_DOUBLE_HIGH (scalar_op1);
 -            if (EXACT_POWER_OF_2_OR_ZERO_P (coeff))
 -              {
 -                int shift = floor_log2 (coeff) + HOST_BITS_PER_WIDE_INT;
 -                if (shift < HOST_BITS_PER_DOUBLE_INT - 1
 -                    || mode_bitsize <= HOST_BITS_PER_DOUBLE_INT)
 -                  return expand_shift (LSHIFT_EXPR, mode, op0,
 -                                       shift, target, unsignedp);
 -              }
 -            goto skip_synth;
 +            /* Any positive number that fits in a word.  */
 +            coeff = CONST_WIDE_INT_ELT (scalar_op1, 0);
            }
          else
            goto skip_synth;
@@@ -3260,6 -3285,7 +3275,6 @@@ choose_multiplier (unsigned HOST_WIDE_I
                   unsigned HOST_WIDE_INT *multiplier_ptr,
                   int *post_shift_ptr, int *lgup_ptr)
  {
 -  double_int mhigh, mlow;
    int lgup, post_shift;
    int pow, pow2;
  
    pow = n + lgup;
    pow2 = n + lgup - precision;
  
 -  /* We could handle this with some effort, but this case is much
 -     better handled directly with a scc insn, so rely on caller using
 -     that.  */
 -  gcc_assert (pow != HOST_BITS_PER_DOUBLE_INT);
 -
    /* mlow = 2^(N + lgup)/d */
 -  double_int val = double_int_zero.set_bit (pow);
 -  mlow = val.div (double_int::from_uhwi (d), true, TRUNC_DIV_EXPR); 
 +  wide_int val = wi::set_bit_in_zero (pow, HOST_BITS_PER_DOUBLE_INT);
 +  wide_int mlow = wi::udiv_trunc (val, d);
  
    /* mhigh = (2^(N + lgup) + 2^(N + lgup - precision))/d */
 -  val |= double_int_zero.set_bit (pow2);
 -  mhigh = val.div (double_int::from_uhwi (d), true, TRUNC_DIV_EXPR);
 -
 -  gcc_assert (!mhigh.high || val.high - d < d);
 -  gcc_assert (mhigh.high <= 1 && mlow.high <= 1);
 -  /* Assert that mlow < mhigh.  */
 -  gcc_assert (mlow.ult (mhigh));
 +  val |= wi::set_bit_in_zero (pow2, HOST_BITS_PER_DOUBLE_INT);
 +  wide_int mhigh = wi::udiv_trunc (val, d);
  
    /* If precision == N, then mlow, mhigh exceed 2^N
       (but they do not exceed 2^(N+1)).  */
    /* Reduce to lowest terms.  */
    for (post_shift = lgup; post_shift > 0; post_shift--)
      {
 -      int shft = HOST_BITS_PER_WIDE_INT - 1;
 -      unsigned HOST_WIDE_INT ml_lo = (mlow.high << shft) | (mlow.low >> 1);
 -      unsigned HOST_WIDE_INT mh_lo = (mhigh.high << shft) | (mhigh.low >> 1);
 +      unsigned HOST_WIDE_INT ml_lo = wi::extract_uhwi (mlow, 1,
 +                                                     HOST_BITS_PER_WIDE_INT);
 +      unsigned HOST_WIDE_INT mh_lo = wi::extract_uhwi (mhigh, 1,
 +                                                     HOST_BITS_PER_WIDE_INT);
        if (ml_lo >= mh_lo)
        break;
  
 -      mlow = double_int::from_uhwi (ml_lo);
 -      mhigh = double_int::from_uhwi (mh_lo);
 +      mlow = wi::uhwi (ml_lo, HOST_BITS_PER_DOUBLE_INT);
 +      mhigh = wi::uhwi (mh_lo, HOST_BITS_PER_DOUBLE_INT);
      }
  
    *post_shift_ptr = post_shift;
    if (n < HOST_BITS_PER_WIDE_INT)
      {
        unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT) 1 << n) - 1;
 -      *multiplier_ptr = mhigh.low & mask;
 -      return mhigh.low >= mask;
 +      *multiplier_ptr = mhigh.to_uhwi () & mask;
 +      return mhigh.to_uhwi () >= mask;
      }
    else
      {
 -      *multiplier_ptr = mhigh.low;
 -      return mhigh.high;
 +      *multiplier_ptr = mhigh.to_uhwi ();
 +      return wi::extract_uhwi (mhigh, HOST_BITS_PER_WIDE_INT, 1);
      }
  }
  
@@@ -3574,9 -3609,9 +3589,9 @@@ expmed_mult_highpart (enum machine_mod
  static rtx
  expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d)
  {
 -  unsigned HOST_WIDE_INT masklow, maskhigh;
    rtx result, temp, shift, label;
    int logd;
 +  int prec = GET_MODE_PRECISION (mode);
  
    logd = floor_log2 (d);
    result = gen_reg_rtx (mode);
                                      mode, 0, -1);
        if (signmask)
        {
 +        HOST_WIDE_INT masklow = ((HOST_WIDE_INT) 1 << logd) - 1;
          signmask = force_reg (mode, signmask);
 -        masklow = ((HOST_WIDE_INT) 1 << logd) - 1;
          shift = GEN_INT (GET_MODE_BITSIZE (mode) - logd);
  
          /* Use the rtx_cost of a LSHIFTRT instruction to determine
       modulus.  By including the signbit in the operation, many targets
       can avoid an explicit compare operation in the following comparison
       against zero.  */
 -
 -  masklow = ((HOST_WIDE_INT) 1 << logd) - 1;
 -  if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
 -    {
 -      masklow |= HOST_WIDE_INT_M1U << (GET_MODE_BITSIZE (mode) - 1);
 -      maskhigh = -1;
 -    }
 -  else
 -    maskhigh = HOST_WIDE_INT_M1U
 -               << (GET_MODE_BITSIZE (mode) - HOST_BITS_PER_WIDE_INT - 1);
 +  wide_int mask = wi::mask (logd, false, GET_MODE_PRECISION (mode));
 +  mask = wi::set_bit (mask, prec - 1);
  
    temp = expand_binop (mode, and_optab, op0,
 -                     immed_double_const (masklow, maskhigh, mode),
 +                     immed_wide_int_const (mask, mode),
                       result, 1, OPTAB_LIB_WIDEN);
    if (temp != result)
      emit_move_insn (result, temp);
  
    temp = expand_binop (mode, sub_optab, result, const1_rtx, result,
                       0, OPTAB_LIB_WIDEN);
 -  masklow = HOST_WIDE_INT_M1U << logd;
 -  maskhigh = -1;
 +
 +  mask = wi::mask (logd, true, GET_MODE_PRECISION (mode));
    temp = expand_binop (mode, ior_optab, temp,
 -                     immed_double_const (masklow, maskhigh, mode),
 +                     immed_wide_int_const (mask, mode),
                       result, 1, OPTAB_LIB_WIDEN);
    temp = expand_binop (mode, add_optab, temp, const1_rtx, result,
                       0, OPTAB_LIB_WIDEN);
@@@ -4898,15 -4941,24 +4913,15 @@@ make_tree (tree type, rtx x
    switch (GET_CODE (x))
      {
      case CONST_INT:
 -      {
 -      HOST_WIDE_INT hi = 0;
 -
 -      if (INTVAL (x) < 0
 -          && !(TYPE_UNSIGNED (type)
 -               && (GET_MODE_BITSIZE (TYPE_MODE (type))
 -                   < HOST_BITS_PER_WIDE_INT)))
 -        hi = -1;
 -
 -      t = build_int_cst_wide (type, INTVAL (x), hi);
 -
 -      return t;
 -      }
 +    case CONST_WIDE_INT:
 +      t = wide_int_to_tree (type, std::make_pair (x, TYPE_MODE (type)));
 +      return t;
  
      case CONST_DOUBLE:
 -      if (GET_MODE (x) == VOIDmode)
 -      t = build_int_cst_wide (type,
 -                              CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x));
 +      if (TARGET_SUPPORTS_WIDE_INT == 0 && GET_MODE (x) == VOIDmode)
 +      t = wide_int_to_tree (type,
 +                            wide_int::from_array (&CONST_DOUBLE_LOW (x), 2,
 +                                                  HOST_BITS_PER_WIDE_INT * 2));
        else
        {
          REAL_VALUE_TYPE d;
diff --combined gcc/expr.c
index 60d9de625823c335b5380651d560f843db843b33,551a66059b9a034a922063df90c1b48e6241de57..c751004c68e4d39dcbc2a665f02e0f4a90a895e2
@@@ -43,12 -43,16 +43,16 @@@ along with GCC; see the file COPYING3
  #include "intl.h"
  #include "tm_p.h"
  #include "tree-iterator.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-ssanames.h"
  #include "target.h"
  #include "common/common-target.h"
  #include "timevar.h"
  #include "df.h"
  #include "diagnostic.h"
+ #include "tree-ssa-live.h"
  #include "tree-outof-ssa.h"
  #include "target-globals.h"
  #include "params.h"
@@@ -711,33 -715,64 +715,33 @@@ convert_modes (enum machine_mode mode, 
    if (mode == oldmode)
      return x;
  
 -  /* There is one case that we must handle specially: If we are converting
 -     a CONST_INT into a mode whose size is twice HOST_BITS_PER_WIDE_INT and
 -     we are to interpret the constant as unsigned, gen_lowpart will do
 -     the wrong if the constant appears negative.  What we want to do is
 -     make the high-order word of the constant zero, not all ones.  */
 -
 -  if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT
 -      && GET_MODE_BITSIZE (mode) == HOST_BITS_PER_DOUBLE_INT
 -      && CONST_INT_P (x) && INTVAL (x) < 0)
 +  if (CONST_SCALAR_INT_P (x) 
 +      && GET_MODE_CLASS (mode) == MODE_INT)
      {
 -      double_int val = double_int::from_uhwi (INTVAL (x));
 -
 -      /* We need to zero extend VAL.  */
 -      if (oldmode != VOIDmode)
 -      val = val.zext (GET_MODE_BITSIZE (oldmode));
 -
 -      return immed_double_int_const (val, mode);
 +      /* If the caller did not tell us the old mode, then there is
 +       not much to do with respect to canonization.  We have to assume
 +       that all the bits are significant.  */
 +      if (GET_MODE_CLASS (oldmode) != MODE_INT)
 +      oldmode = MAX_MODE_INT;
 +      wide_int w = wide_int::from (std::make_pair (x, oldmode),
 +                                 GET_MODE_PRECISION (mode),
 +                                 unsignedp ? UNSIGNED : SIGNED);
 +      return immed_wide_int_const (w, mode);
      }
  
    /* We can do this with a gen_lowpart if both desired and current modes
       are integer, and this is either a constant integer, a register, or a
 -     non-volatile MEM.  Except for the constant case where MODE is no
 -     wider than HOST_BITS_PER_WIDE_INT, we must be narrowing the operand.  */
 -
 -  if ((CONST_INT_P (x)
 -       && GET_MODE_PRECISION (mode) <= HOST_BITS_PER_WIDE_INT)
 -      || (GET_MODE_CLASS (mode) == MODE_INT
 -        && GET_MODE_CLASS (oldmode) == MODE_INT
 -        && (CONST_DOUBLE_AS_INT_P (x) 
 -            || (GET_MODE_PRECISION (mode) <= GET_MODE_PRECISION (oldmode)
 -                && ((MEM_P (x) && ! MEM_VOLATILE_P (x)
 -                     && direct_load[(int) mode])
 -                    || (REG_P (x)
 -                        && (! HARD_REGISTER_P (x)
 -                            || HARD_REGNO_MODE_OK (REGNO (x), mode))
 -                        && TRULY_NOOP_TRUNCATION_MODES_P (mode,
 -                                                          GET_MODE (x))))))))
 -    {
 -      /* ?? If we don't know OLDMODE, we have to assume here that
 -       X does not need sign- or zero-extension.   This may not be
 -       the case, but it's the best we can do.  */
 -      if (CONST_INT_P (x) && oldmode != VOIDmode
 -        && GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (oldmode))
 -      {
 -        HOST_WIDE_INT val = INTVAL (x);
 -
 -        /* We must sign or zero-extend in this case.  Start by
 -           zero-extending, then sign extend if we need to.  */
 -        val &= GET_MODE_MASK (oldmode);
 -        if (! unsignedp
 -            && val_signbit_known_set_p (oldmode, val))
 -          val |= ~GET_MODE_MASK (oldmode);
 -
 -        return gen_int_mode (val, mode);
 -      }
 -
 -      return gen_lowpart (mode, x);
 -    }
 +     non-volatile MEM. */
 +  if (GET_MODE_CLASS (mode) == MODE_INT
 +      && GET_MODE_CLASS (oldmode) == MODE_INT
 +      && GET_MODE_PRECISION (mode) <= GET_MODE_PRECISION (oldmode)
 +      && ((MEM_P (x) && !MEM_VOLATILE_P (x) && direct_load[(int) mode])
 +          || (REG_P (x)
 +              && (!HARD_REGISTER_P (x)
 +                  || HARD_REGNO_MODE_OK (REGNO (x), mode))
 +              && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x)))))
 +
 +   return gen_lowpart (mode, x);
  
    /* Converting from integer constant into mode is always equivalent to an
       subreg operation.  */
@@@ -1719,7 -1754,6 +1723,7 @@@ emit_group_load_1 (rtx *tmps, rtx dst, 
            {
              rtx first, second;
  
 +            /* TODO: const_wide_int can have sizes other than this...  */
              gcc_assert (2 * len == ssize);
              split_double (src, &first, &second);
              if (i)
@@@ -4530,14 -4564,14 +4534,14 @@@ get_bit_range (unsigned HOST_WIDE_INT *
       relative to the representative.  DECL_FIELD_OFFSET of field and
       repr are the same by construction if they are not constants,
       see finish_bitfield_layout.  */
 -  if (host_integerp (DECL_FIELD_OFFSET (field), 1)
 -      && host_integerp (DECL_FIELD_OFFSET (repr), 1))
 -    bitoffset = (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
 -               - tree_low_cst (DECL_FIELD_OFFSET (repr), 1)) * BITS_PER_UNIT;
 +  if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field))
 +      && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr)))
 +    bitoffset = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
 +               - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT;
    else
      bitoffset = 0;
 -  bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
 -              - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
 +  bitoffset += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
 +              - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
  
    /* If the adjustment is larger than bitpos, we would have a negative bit
       position for the lower bound and this may wreak havoc later.  This can
    else
      *bitstart = *bitpos - bitoffset;
  
 -  *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1;
 +  *bitend = *bitstart + tree_to_uhwi (DECL_SIZE (repr)) - 1;
  }
  
  /* Returns true if ADDR is an ADDR_EXPR of a DECL that does not reside
@@@ -5178,10 -5212,10 +5182,10 @@@ store_expr (tree exp, rtx target, int c
                               &alt_rtl);
      }
  
 -  /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not
 -     the same as that of TARGET, adjust the constant.  This is needed, for
 -     example, in case it is a CONST_DOUBLE and we want only a word-sized
 -     value.  */
 +  /* If TEMP is a VOIDmode constant and the mode of the type of EXP is
 +     not the same as that of TARGET, adjust the constant.  This is
 +     needed, for example, in case it is a CONST_DOUBLE or
 +     CONST_WIDE_INT and we want only a word-sized value.  */
    if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode
        && TREE_CODE (exp) != ERROR_MARK
        && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
@@@ -5374,11 -5408,11 +5378,11 @@@ count_type_elements (const_tree type, b
        tree nelts;
  
        nelts = array_type_nelts (type);
 -      if (nelts && host_integerp (nelts, 1))
 +      if (nelts && tree_fits_uhwi_p (nelts))
          {
            unsigned HOST_WIDE_INT n;
  
 -          n = tree_low_cst (nelts, 1) + 1;
 +          n = tree_to_uhwi (nelts) + 1;
            if (n == 0 || for_ctor_p)
              return n;
            else
@@@ -5493,9 -5527,9 +5497,9 @@@ categorize_ctor_elements_1 (const_tree 
          tree lo_index = TREE_OPERAND (purpose, 0);
          tree hi_index = TREE_OPERAND (purpose, 1);
  
 -        if (host_integerp (lo_index, 1) && host_integerp (hi_index, 1))
 -          mult = (tree_low_cst (hi_index, 1)
 -                  - tree_low_cst (lo_index, 1) + 1);
 +        if (tree_fits_uhwi_p (lo_index) && tree_fits_uhwi_p (hi_index))
 +          mult = (tree_to_uhwi (hi_index)
 +                  - tree_to_uhwi (lo_index) + 1);
        }
        num_fields += mult;
        elt_type = TREE_TYPE (value);
@@@ -5795,8 -5829,8 +5799,8 @@@ store_constructor (tree exp, rtx target
            if (cleared && initializer_zerop (value))
              continue;
  
 -          if (host_integerp (DECL_SIZE (field), 1))
 -            bitsize = tree_low_cst (DECL_SIZE (field), 1);
 +          if (tree_fits_uhwi_p (DECL_SIZE (field)))
 +            bitsize = tree_to_uhwi (DECL_SIZE (field));
            else
              bitsize = -1;
  
              mode = VOIDmode;
  
            offset = DECL_FIELD_OFFSET (field);
 -          if (host_integerp (offset, 0)
 -              && host_integerp (bit_position (field), 0))
 +          if (tree_fits_shwi_p (offset)
 +              && tree_fits_shwi_p (bit_position (field)))
              {
                bitpos = int_bit_position (field);
                offset = 0;
              }
            else
 -            bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
 +            bitpos = tree_to_shwi (DECL_FIELD_BIT_OFFSET (field));
  
            if (offset)
              {
        domain = TYPE_DOMAIN (type);
        const_bounds_p = (TYPE_MIN_VALUE (domain)
                          && TYPE_MAX_VALUE (domain)
 -                        && host_integerp (TYPE_MIN_VALUE (domain), 0)
 -                        && host_integerp (TYPE_MAX_VALUE (domain), 0));
 +                        && tree_fits_shwi_p (TYPE_MIN_VALUE (domain))
 +                        && tree_fits_shwi_p (TYPE_MAX_VALUE (domain)));
  
        /* If we have constant bounds for the range of the type, get them.  */
        if (const_bounds_p)
          {
 -          minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
 -          maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
 +          minelt = tree_to_shwi (TYPE_MIN_VALUE (domain));
 +          maxelt = tree_to_shwi (TYPE_MAX_VALUE (domain));
          }
  
        /* If the constructor has fewer elements than the array, clear
                    tree lo_index = TREE_OPERAND (index, 0);
                    tree hi_index = TREE_OPERAND (index, 1);
  
 -                  if (! host_integerp (lo_index, 1)
 -                      || ! host_integerp (hi_index, 1))
 +                  if (! tree_fits_uhwi_p (lo_index)
 +                      || ! tree_fits_uhwi_p (hi_index))
                      {
                        need_to_clear = 1;
                        break;
                      }
  
 -                  this_node_count = (tree_low_cst (hi_index, 1)
 -                                     - tree_low_cst (lo_index, 1) + 1);
 +                  this_node_count = (tree_to_uhwi (hi_index)
 +                                     - tree_to_uhwi (lo_index) + 1);
                  }
                else
                  this_node_count = 1;
  
            mode = TYPE_MODE (elttype);
            if (mode == BLKmode)
 -            bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
 -                       ? tree_low_cst (TYPE_SIZE (elttype), 1)
 +            bitsize = (tree_fits_uhwi_p (TYPE_SIZE (elttype))
 +                       ? tree_to_uhwi (TYPE_SIZE (elttype))
                         : -1);
            else
              bitsize = GET_MODE_BITSIZE (mode);
  
                /* If the range is constant and "small", unroll the loop.  */
                if (const_bounds_p
 -                  && host_integerp (lo_index, 0)
 -                  && host_integerp (hi_index, 0)
 -                  && (lo = tree_low_cst (lo_index, 0),
 -                      hi = tree_low_cst (hi_index, 0),
 +                  && tree_fits_shwi_p (lo_index)
 +                  && tree_fits_shwi_p (hi_index)
 +                  && (lo = tree_to_shwi (lo_index),
 +                      hi = tree_to_shwi (hi_index),
                        count = hi - lo + 1,
                        (!MEM_P (target)
                         || count <= 2
 -                       || (host_integerp (TYPE_SIZE (elttype), 1)
 -                           && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
 +                       || (tree_fits_uhwi_p (TYPE_SIZE (elttype))
 +                           && (tree_to_uhwi (TYPE_SIZE (elttype)) * count
                                 <= 40 * 8)))))
                  {
                    lo -= minelt;  hi -= minelt;
                    for (; lo <= hi; lo++)
                      {
 -                      bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
 +                      bitpos = lo * tree_to_shwi (TYPE_SIZE (elttype));
  
                        if (MEM_P (target)
                            && !MEM_KEEP_ALIAS_SET_P (target)
                    emit_label (loop_end);
                  }
              }
 -          else if ((index != 0 && ! host_integerp (index, 0))
 -                   || ! host_integerp (TYPE_SIZE (elttype), 1))
 +          else if ((index != 0 && ! tree_fits_shwi_p (index))
 +                   || ! tree_fits_uhwi_p (TYPE_SIZE (elttype)))
              {
                tree position;
  
            else
              {
                if (index != 0)
 -                bitpos = ((tree_low_cst (index, 0) - minelt)
 -                          * tree_low_cst (TYPE_SIZE (elttype), 1));
 +                bitpos = ((tree_to_shwi (index) - minelt)
 +                          * tree_to_uhwi (TYPE_SIZE (elttype)));
                else
 -                bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
 +                bitpos = (i * tree_to_uhwi (TYPE_SIZE (elttype)));
  
                if (MEM_P (target) && !MEM_KEEP_ALIAS_SET_P (target)
                    && TREE_CODE (type) == ARRAY_TYPE
        int need_to_clear;
        int icode = CODE_FOR_nothing;
        tree elttype = TREE_TYPE (type);
 -      int elt_size = tree_low_cst (TYPE_SIZE (elttype), 1);
 +      int elt_size = tree_to_uhwi (TYPE_SIZE (elttype));
        enum machine_mode eltmode = TYPE_MODE (elttype);
        HOST_WIDE_INT bitsize;
        HOST_WIDE_INT bitpos;
  
            FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
              {
 -              int n_elts_here = tree_low_cst
 +              int n_elts_here = tree_to_uhwi
                  (int_const_binop (TRUNC_DIV_EXPR,
                                    TYPE_SIZE (TREE_TYPE (value)),
 -                                  TYPE_SIZE (elttype)), 1);
 +                                  TYPE_SIZE (elttype)));
  
                count += n_elts_here;
                if (mostly_zeros_p (value))
            HOST_WIDE_INT eltpos;
            tree value = ce->value;
  
 -          bitsize = tree_low_cst (TYPE_SIZE (TREE_TYPE (value)), 1);
 +          bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (value)));
            if (cleared && initializer_zerop (value))
              continue;
  
            if (ce->index)
 -            eltpos = tree_low_cst (ce->index, 1);
 +            eltpos = tree_to_uhwi (ce->index);
            else
              eltpos = i;
  
@@@ -6513,7 -6547,7 +6517,7 @@@ get_inner_reference (tree exp, HOST_WID
    enum machine_mode mode = VOIDmode;
    bool blkmode_bitfield = false;
    tree offset = size_zero_node;
 -  double_int bit_offset = double_int_zero;
 +  offset_int bit_offset = 0;
  
    /* First get the mode, signedness, and size.  We do this from just the
       outermost expression.  */
      {
        tree field = TREE_OPERAND (exp, 1);
        size_tree = DECL_SIZE (field);
-       if (!DECL_BIT_FIELD (field))
-       mode = DECL_MODE (field);
-       else if (DECL_MODE (field) == BLKmode)
-       blkmode_bitfield = true;
-       else if (TREE_THIS_VOLATILE (exp)
-              && flag_strict_volatile_bitfields > 0)
+       if (flag_strict_volatile_bitfields > 0
+         && TREE_THIS_VOLATILE (exp)
+         && DECL_BIT_FIELD_TYPE (field)
+         && DECL_MODE (field) != BLKmode)
        /* Volatile bitfields should be accessed in the mode of the
             field's type, not the mode computed based on the bit
             size.  */
        mode = TYPE_MODE (DECL_BIT_FIELD_TYPE (field));
+       else if (!DECL_BIT_FIELD (field))
+       mode = DECL_MODE (field);
+       else if (DECL_MODE (field) == BLKmode)
+       blkmode_bitfield = true;
  
        *punsignedp = DECL_UNSIGNED (field);
      }
  
    if (size_tree != 0)
      {
 -      if (! host_integerp (size_tree, 1))
 +      if (! tree_fits_uhwi_p (size_tree))
        mode = BLKmode, *pbitsize = -1;
        else
 -      *pbitsize = tree_low_cst (size_tree, 1);
 +      *pbitsize = tree_to_uhwi (size_tree);
      }
  
    /* Compute cumulative bit-offset for nested component-refs and array-refs,
        switch (TREE_CODE (exp))
        {
        case BIT_FIELD_REF:
 -        bit_offset += tree_to_double_int (TREE_OPERAND (exp, 2));
 +        bit_offset += wi::to_offset (TREE_OPERAND (exp, 2));
          break;
  
        case COMPONENT_REF:
              break;
  
            offset = size_binop (PLUS_EXPR, offset, this_offset);
 -          bit_offset += tree_to_double_int (DECL_FIELD_BIT_OFFSET (field));
 +          bit_offset += wi::to_offset (DECL_FIELD_BIT_OFFSET (field));
  
            /* ??? Right now we don't do anything with DECL_OFFSET_ALIGN.  */
          }
          break;
  
        case IMAGPART_EXPR:
 -        bit_offset += double_int::from_uhwi (*pbitsize);
 +        bit_offset += *pbitsize;
          break;
  
        case VIEW_CONVERT_EXPR:
              tree off = TREE_OPERAND (exp, 1);
              if (!integer_zerop (off))
                {
 -                double_int boff, coff = mem_ref_offset (exp);
 -                boff = coff.lshift (BITS_PER_UNIT == 8
 -                                    ? 3 : exact_log2 (BITS_PER_UNIT));
 +                offset_int boff, coff = mem_ref_offset (exp);
 +                boff = wi::lshift (coff, (BITS_PER_UNIT == 8
 +                                          ? 3 : exact_log2 (BITS_PER_UNIT)));
                  bit_offset += boff;
                }
              exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
       this conversion.  */
    if (TREE_CODE (offset) == INTEGER_CST)
      {
 -      double_int tem = tree_to_double_int (offset);
 -      tem = tem.sext (TYPE_PRECISION (sizetype));
 -      tem = tem.lshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT));
 +      offset_int tem = wi::sext (wi::to_offset (offset),
 +                               TYPE_PRECISION (sizetype));
 +      tem = wi::lshift (tem, (BITS_PER_UNIT == 8
 +                            ? 3 : exact_log2 (BITS_PER_UNIT)));
        tem += bit_offset;
 -      if (tem.fits_shwi ())
 +      if (wi::fits_shwi_p (tem))
        {
          *pbitpos = tem.to_shwi ();
          *poffset = offset = NULL_TREE;
    if (offset)
      {
        /* Avoid returning a negative bitpos as this may wreak havoc later.  */
 -      if (bit_offset.is_negative ())
 +      if (wi::neg_p (bit_offset))
          {
 -        double_int mask
 -          = double_int::mask (BITS_PER_UNIT == 8
 -                             ? 3 : exact_log2 (BITS_PER_UNIT));
 -        double_int tem = bit_offset.and_not (mask);
 +        offset_int mask
 +          = wi::mask <offset_int> (BITS_PER_UNIT == 8
 +                                   ? 3 : exact_log2 (BITS_PER_UNIT),
 +                                   false);
 +        offset_int tem = bit_offset.and_not (mask);
          /* TEM is the bitpos rounded to BITS_PER_UNIT towards -Inf.
             Subtract it to BIT_OFFSET and add it (scaled) to OFFSET.  */
          bit_offset -= tem;
 -        tem = tem.arshift (BITS_PER_UNIT == 8
 -                           ? 3 : exact_log2 (BITS_PER_UNIT),
 -                           HOST_BITS_PER_DOUBLE_INT);
 +        tem = wi::arshift (tem, (BITS_PER_UNIT == 8
 +                                 ? 3 : exact_log2 (BITS_PER_UNIT)));
          offset = size_binop (PLUS_EXPR, offset,
 -                             double_int_to_tree (sizetype, tem));
 +                             wide_int_to_tree (sizetype, tem));
        }
  
        *pbitpos = bit_offset.to_shwi ();
@@@ -7248,72 -7283,14 +7254,14 @@@ safe_from_p (const_rtx x, tree exp, in
  unsigned HOST_WIDE_INT
  highest_pow2_factor (const_tree exp)
  {
-   unsigned HOST_WIDE_INT c0, c1;
-   switch (TREE_CODE (exp))
-     {
-     case INTEGER_CST:
-       /* We can find the lowest bit that's a one.  If the low
-        HOST_BITS_PER_WIDE_INT bits are zero, return BIGGEST_ALIGNMENT.
-        We need to handle this case since we can find it in a COND_EXPR,
-        a MIN_EXPR, or a MAX_EXPR.  If the constant overflows, we have an
-        erroneous program, so return BIGGEST_ALIGNMENT to avoid any
-        later ICE.  */
-       if (TREE_OVERFLOW (exp))
-       return BIGGEST_ALIGNMENT;
-       else
-       {
-         c0 = tree_to_hwi (exp);
-         c0 &= -c0;
-         return c0 ? c0 : BIGGEST_ALIGNMENT;
-       }
-       break;
-     case PLUS_EXPR:  case MINUS_EXPR:  case MIN_EXPR:  case MAX_EXPR:
-       c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
-       c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
-       return MIN (c0, c1);
-     case MULT_EXPR:
-       c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
-       c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
-       return c0 * c1;
-     case ROUND_DIV_EXPR:  case TRUNC_DIV_EXPR:  case FLOOR_DIV_EXPR:
-     case CEIL_DIV_EXPR:
-       if (integer_pow2p (TREE_OPERAND (exp, 1))
-         && tree_fits_uhwi_p (TREE_OPERAND (exp, 1)))
-       {
-         c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
-         c1 = tree_to_uhwi (TREE_OPERAND (exp, 1));
-         return MAX (1, c0 / c1);
-       }
-       break;
-     case BIT_AND_EXPR:
-       /* The highest power of two of a bit-and expression is the maximum of
-        that of its operands.  We typically get here for a complex LHS and
-        a constant negative power of two on the RHS to force an explicit
-        alignment, so don't bother looking at the LHS.  */
-       return highest_pow2_factor (TREE_OPERAND (exp, 1));
-     CASE_CONVERT:
-     case SAVE_EXPR:
-       return highest_pow2_factor (TREE_OPERAND (exp, 0));
-     case COMPOUND_EXPR:
-       return highest_pow2_factor (TREE_OPERAND (exp, 1));
-     case COND_EXPR:
-       c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
-       c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
-       return MIN (c0, c1);
-     default:
-       break;
-     }
-   return 1;
+   unsigned HOST_WIDE_INT ret;
+   int trailing_zeros = tree_ctz (exp);
+   if (trailing_zeros >= HOST_BITS_PER_WIDE_INT)
+     return BIGGEST_ALIGNMENT;
+   ret = (unsigned HOST_WIDE_INT) 1 << trailing_zeros;
+   if (ret > BIGGEST_ALIGNMENT)
+     return BIGGEST_ALIGNMENT;
+   return ret;
  }
  
  /* Similar, except that the alignment requirements of TARGET are
@@@ -7686,12 -7663,11 +7634,12 @@@ expand_constructor (tree exp, rtx targe
  
    /* All elts simple constants => refer to a constant in memory.  But
       if this is a non-BLKmode mode, let it store a field at a time
 -     since that should make a CONST_INT or CONST_DOUBLE when we
 -     fold.  Likewise, if we have a target we can use, it is best to
 -     store directly into the target unless the type is large enough
 -     that memcpy will be used.  If we are making an initializer and
 -     all operands are constant, put it in memory as well.
 +     since that should make a CONST_INT, CONST_WIDE_INT or
 +     CONST_DOUBLE when we fold.  Likewise, if we have a target we can
 +     use, it is best to store directly into the target unless the type
 +     is large enough that memcpy will be used.  If we are making an
 +     initializer and all operands are constant, put it in memory as
 +     well.
  
       FIXME: Avoid trying to fill vector constructors piece-meal.
       Output them with output_constant_def below unless we're sure
         && ((mode == BLKmode
            && ! (target != 0 && safe_from_p (target, exp, 1)))
                  || TREE_ADDRESSABLE (exp)
 -                || (host_integerp (TYPE_SIZE_UNIT (type), 1)
 +                || (tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
                      && (! MOVE_BY_PIECES_P
 -                                   (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
 +                                   (tree_to_uhwi (TYPE_SIZE_UNIT (type)),
                                      TYPE_ALIGN (type)))
                      && ! mostly_zeros_p (exp))))
        || ((modifier == EXPAND_INITIALIZER || modifier == EXPAND_CONST_ADDRESS)
@@@ -8161,18 -8137,17 +8109,18 @@@ expand_expr_real_2 (sepops ops, rtx tar
              && TREE_CONSTANT (treeop1))
            {
              rtx constant_part;
 +            HOST_WIDE_INT wc;
 +            enum machine_mode wmode = TYPE_MODE (TREE_TYPE (treeop1));
  
              op1 = expand_expr (treeop1, subtarget, VOIDmode,
                                 EXPAND_SUM);
 -            /* Use immed_double_const to ensure that the constant is
 +            /* Use wi::shwi to ensure that the constant is
                 truncated according to the mode of OP1, then sign extended
                 to a HOST_WIDE_INT.  Using the constant directly can result
                 in non-canonical RTL in a 64x32 cross compile.  */
 -            constant_part
 -              = immed_double_const (TREE_INT_CST_LOW (treeop0),
 -                                    (HOST_WIDE_INT) 0,
 -                                    TYPE_MODE (TREE_TYPE (treeop1)));
 +            wc = tree_to_hwi (treeop0);
 +            constant_part =
 +              immed_wide_int_const (wi::shwi (wc, wmode), wmode);
              op1 = plus_constant (mode, op1, INTVAL (constant_part));
              if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                op1 = force_operand (op1, target);
                   && TREE_CONSTANT (treeop0))
            {
              rtx constant_part;
 +            HOST_WIDE_INT wc;
 +            enum machine_mode wmode = TYPE_MODE (TREE_TYPE (treeop0));
  
              op0 = expand_expr (treeop0, subtarget, VOIDmode,
                                 (modifier == EXPAND_INITIALIZER
                    return simplify_gen_binary (PLUS, mode, op0, op1);
                  goto binop2;
                }
 -            /* Use immed_double_const to ensure that the constant is
 +            /* Use wi::shwi to ensure that the constant is
                 truncated according to the mode of OP1, then sign extended
                 to a HOST_WIDE_INT.  Using the constant directly can result
                 in non-canonical RTL in a 64x32 cross compile.  */
 +            wc = tree_to_hwi (treeop1);
              constant_part
 -              = immed_double_const (TREE_INT_CST_LOW (treeop1),
 -                                    (HOST_WIDE_INT) 0,
 -                                    TYPE_MODE (TREE_TYPE (treeop0)));
 +              = immed_wide_int_const (wi::shwi (wc, wmode), wmode);
              op0 = plus_constant (mode, op0, INTVAL (constant_part));
              if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                op0 = force_operand (op0, target);
         indexed address, for machines that support that.  */
  
        if (modifier == EXPAND_SUM && mode == ptr_mode
 -        && host_integerp (treeop1, 0))
 +        && tree_fits_shwi_p (treeop1))
        {
          tree exp1 = treeop1;
  
            op0 = copy_to_mode_reg (mode, op0);
  
          return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
 -                             gen_int_mode (tree_low_cst (exp1, 0),
 -                                           TYPE_MODE (TREE_TYPE (exp1)))));
 +           gen_int_mode (tree_to_shwi (exp1), TYPE_MODE (TREE_TYPE (exp1)))));
        }
  
        if (modifier == EXPAND_STACK_PARM)
         for unsigned bitfield expand this as XOR with a proper constant
         instead.  */
        if (reduce_bit_field && TYPE_UNSIGNED (type))
 -      temp = expand_binop (mode, xor_optab, op0,
 -                           immed_double_int_const
 -                             (double_int::mask (TYPE_PRECISION (type)), mode),
 -                           target, 1, OPTAB_LIB_WIDEN);
 +      {
 +        wide_int mask = wi::mask (TYPE_PRECISION (type),
 +                                  false, GET_MODE_PRECISION (mode));
 +
 +        temp = expand_binop (mode, xor_optab, op0,
 +                             immed_wide_int_const (mask, mode),
 +                             target, 1, OPTAB_LIB_WIDEN);
 +      }
        else
        temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
        gcc_assert (temp);
@@@ -9392,19 -9363,11 +9340,19 @@@ expand_expr_real_1 (tree exp, rtx targe
        return decl_rtl;
  
      case INTEGER_CST:
 -      temp = immed_double_const (TREE_INT_CST_LOW (exp),
 -                               TREE_INT_CST_HIGH (exp), mode);
 -
 -      return temp;
 -
 +      {
 +      tree type = TREE_TYPE (exp);
 +      /* One could argue that GET_MODE_PRECISION (TYPE_MODE (type))
 +         should always be the same as TYPE_PRECISION (type).
 +         However, it is not.  Since we are converting from tree to
 +         rtl, we have to expose this ugly truth here.  */
 +      temp = immed_wide_int_const (wide_int::from
 +                                     (exp,
 +                                      GET_MODE_PRECISION (TYPE_MODE (type)),
 +                                      TYPE_SIGN (type)),
 +                                   TYPE_MODE (type));
 +      return temp;
 +      }
      case VECTOR_CST:
        {
        tree tmp = NULL_TREE;
           might end up in a register.  */
        if (mem_ref_refers_to_non_mem_p (exp))
          {
 -          HOST_WIDE_INT offset = mem_ref_offset (exp).low;
 +          HOST_WIDE_INT offset = mem_ref_offset (exp).to_short_addr ();
            base = TREE_OPERAND (base, 0);
            if (offset == 0
 -              && host_integerp (TYPE_SIZE (type), 1)
 +              && tree_fits_uhwi_p (TYPE_SIZE (type))
                && (GET_MODE_BITSIZE (DECL_MODE (base))
 -                  == TREE_INT_CST_LOW (TYPE_SIZE (type))))
 +                  == tree_to_uhwi (TYPE_SIZE (type))))
              return expand_expr (build1 (VIEW_CONVERT_EXPR, type, base),
                                  target, tmode, modifier);
            if (TYPE_MODE (type) == BLKmode)
          }
        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);
                  {
                    tree type = TREE_TYPE (TREE_TYPE (init));
                    enum machine_mode mode = TYPE_MODE (type);
 -
 +                  
                    if (GET_MODE_CLASS (mode) == MODE_INT
                        && GET_MODE_SIZE (mode) == 1)
                      return gen_int_mode (TREE_STRING_POINTER (init)
 -                                         [TREE_INT_CST_LOW (index1)],
 +                                         [tree_to_hwi (index1)],
                                           mode);
                  }
              }
                op0 = expand_expr (value, target, tmode, modifier);
                if (DECL_BIT_FIELD (field))
                  {
 -                  HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (DECL_SIZE (field));
 +                  HOST_WIDE_INT bitsize = tree_to_hwi (DECL_SIZE (field));
                    enum machine_mode imode = TYPE_MODE (TREE_TYPE (field));
  
                    if (TYPE_UNSIGNED (TREE_TYPE (field)))
@@@ -10487,10 -10451,9 +10435,10 @@@ reduce_to_bit_field_precision (rtx exp
      }
    else if (TYPE_UNSIGNED (type))
      {
 -      rtx mask = immed_double_int_const (double_int::mask (prec),
 -                                       GET_MODE (exp));
 -      return expand_and (GET_MODE (exp), exp, mask, target);
 +      enum machine_mode mode = GET_MODE (exp);
 +      rtx mask = immed_wide_int_const 
 +      (wi::mask (prec, false, GET_MODE_PRECISION (mode)), mode);
 +      return expand_and (mode, exp, mask, target);
      }
    else
      {
@@@ -10516,10 -10479,10 +10464,10 @@@ is_aligning_offset (const_tree offset, 
    /* We must now have a BIT_AND_EXPR with a constant that is one less than
       power of 2 and which is larger than BIGGEST_ALIGNMENT.  */
    if (TREE_CODE (offset) != BIT_AND_EXPR
 -      || !host_integerp (TREE_OPERAND (offset, 1), 1)
 +      || !tree_fits_uhwi_p (TREE_OPERAND (offset, 1))
        || compare_tree_int (TREE_OPERAND (offset, 1),
                           BIGGEST_ALIGNMENT / BITS_PER_UNIT) <= 0
 -      || !exact_log2 (tree_low_cst (TREE_OPERAND (offset, 1), 1) + 1) < 0)
 +      || !exact_log2 (tree_to_uhwi (TREE_OPERAND (offset, 1)) + 1) < 0)
      return 0;
  
    /* Look at the first operand of BIT_AND_EXPR and strip any conversion.
@@@ -10654,7 -10617,7 +10602,7 @@@ string_constant (tree arg, tree *ptr_of
         and inside of the bounds of the string literal.  */
        offset = fold_convert (sizetype, offset);
        if (compare_tree_int (DECL_SIZE_UNIT (array), length) > 0
 -        && (! host_integerp (offset, 1)
 +        && (! tree_fits_uhwi_p (offset)
              || compare_tree_int (offset, length) >= 0))
        return 0;
  
@@@ -11064,8 -11027,8 +11012,8 @@@ const_vector_from_tree (tree exp
        RTVEC_ELT (v, i) = CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (elt),
                                                         inner);
        else
 -      RTVEC_ELT (v, i) = immed_double_int_const (tree_to_double_int (elt),
 -                                                 inner);
 +      RTVEC_ELT (v, i) 
 +        = immed_wide_int_const (elt, TYPE_MODE (TREE_TYPE (elt)));
      }
  
    return gen_rtx_CONST_VECTOR (mode, v);
diff --combined 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"
  
@@@ -94,8 -94,8 +94,8 @@@ struct locate_and_pad_arg_dat
  #define ADD_PARM_SIZE(TO, INC)                                        \
  do {                                                          \
    tree inc = (INC);                                           \
 -  if (host_integerp (inc, 0))                                 \
 -    (TO).constant += tree_low_cst (inc, 0);                   \
 +  if (tree_fits_shwi_p (inc))                                 \
 +    (TO).constant += tree_to_shwi (inc);                      \
    else if ((TO).var == 0)                                     \
      (TO).var = fold_convert (ssizetype, inc);                 \
    else                                                                \
  #define SUB_PARM_SIZE(TO, DEC)                                        \
  do {                                                          \
    tree dec = (DEC);                                           \
 -  if (host_integerp (dec, 0))                                 \
 -    (TO).constant -= tree_low_cst (dec, 0);                   \
 +  if (tree_fits_shwi_p (dec))                                 \
 +    (TO).constant -= tree_to_shwi (dec);                      \
    else if ((TO).var == 0)                                     \
      (TO).var = size_binop (MINUS_EXPR, ssize_int (0),         \
                           fold_convert (ssizetype, dec));      \
diff --combined gcc/final.c
index 8a9b48f631bc282dfd2e08424f208121932f386f,efefe1a8ee5506657f4bb644e7feeaa9306a4c40..052103cd0ea07eaac29422fa1a84c0ba0beaa93d
@@@ -70,15 -70,14 +70,15 @@@ along with GCC; see the file COPYING3
  #include "debug.h"
  #include "expr.h"
  #include "tree-pass.h"
- #include "tree-ssa.h"
  #include "cgraph.h"
+ #include "tree-ssa.h"
  #include "coverage.h"
  #include "df.h"
  #include "ggc.h"
  #include "cfgloop.h"
  #include "params.h"
  #include "tree-pretty-print.h" /* for dump_function_header */
 +#include "wide-int-print.h"
  
  #ifdef XCOFF_DEBUGGING_INFO
  #include "xcoffout.h"         /* Needed for external data
@@@ -3882,21 -3881,8 +3882,21 @@@ output_addr_const (FILE *file, rtx x
        output_addr_const (file, XEXP (x, 0));
        break;
  
 +    case CONST_WIDE_INT:
 +      /* We do not know the mode here so we have to use a round about
 +       way to build a wide-int to get it printed properly.  */
 +      {
 +      wide_int w = wide_int::from_array (&CONST_WIDE_INT_ELT (x, 0),
 +                                         CONST_WIDE_INT_NUNITS (x),
 +                                         CONST_WIDE_INT_NUNITS (x) 
 +                                         * HOST_BITS_PER_WIDE_INT,
 +                                         false);
 +      print_decs (w, file);
 +      }
 +      break;
 +
      case CONST_DOUBLE:
 -      if (GET_MODE (x) == VOIDmode)
 +      if (CONST_DOUBLE_AS_INT_P (x))
        {
          /* We can use %d if the number is one word and positive.  */
          if (CONST_DOUBLE_HIGH (x))
diff --combined gcc/fold-const.c
index 296b7ec24b8a344996ffc3f6412da9b65f20af85,c346063f925d9fe61d9eef871ce14eabd3ed6853..2a5665f186567de741bd90839d8c515c9f505069
@@@ -58,7 -58,7 +58,7 @@@ along with GCC; see the file COPYING3
  #include "langhooks.h"
  #include "md5.h"
  #include "gimple.h"
- #include "tree-ssa.h"
+ #include "tree-dfa.h"
  
  /* Nonzero if we are folding constants inside an initializer; zero
     otherwise.  */
@@@ -107,6 -107,7 +107,6 @@@ static tree decode_field_reference (loc
                                    HOST_WIDE_INT *,
                                    enum machine_mode *, int *, int *,
                                    tree *, tree *);
 -static int all_ones_mask_p (const_tree, int);
  static tree sign_bit_p (tree, const_tree);
  static int simple_operand_p (const_tree);
  static bool simple_operand_p_2 (tree);
@@@ -163,39 -164,26 +163,39 @@@ protected_set_expr_location_unshare (tr
    return x;
  }
  \f
 -/* If ARG2 divides ARG1 with zero remainder, carries out the division
 -   of type CODE and returns the quotient.
 -   Otherwise returns NULL_TREE.  */
 +/* If ARG2 divides ARG1 with zero remainder, carries out the exact
 +   division and returns the quotient.  Otherwise returns
 +   NULL_TREE.  */
  
  tree
 -div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
 +div_if_zero_remainder (const_tree arg1, const_tree arg2)
  {
 -  double_int quo, rem;
 -  int uns;
 +  wide_int quo;
 +  wide_int warg1 = arg1;
 +  wide_int warg2 = arg2;
 +  signop sgn = TYPE_SIGN (TREE_TYPE (arg1));
 +  signop sgn2 = TYPE_SIGN (TREE_TYPE (arg2));
  
 -  /* The sign of the division is according to operand two, that
 -     does the correct thing for POINTER_PLUS_EXPR where we want
 -     a signed division.  */
 -  uns = TYPE_UNSIGNED (TREE_TYPE (arg2));
 -
 -  quo = tree_to_double_int (arg1).divmod (tree_to_double_int (arg2),
 -                                        uns, code, &rem);
 +  if (sgn != sgn2)
 +    {
 +      /* When signedness mismatches, we promote the unsigned value to
 +       a signed value.  We preserve the value by extending the
 +       precision by 1 bit, iff the top bit is set.  */
 +      if (sgn == UNSIGNED)
 +      {
 +        if (wi::neg_p (warg1))
 +          warg1 = wide_int::from (warg1, warg1.get_precision () + 1, sgn);
 +        sgn = SIGNED;
 +      }
 +      else
 +      {
 +        if (wi::neg_p (warg2))
 +          warg2 = wide_int::from (warg2, warg2.get_precision () + 1, sgn2);
 +      }
 +    }
  
 -  if (rem.is_zero ())
 -    return build_int_cst_wide (TREE_TYPE (arg1), quo.low, quo.high);
 +  if (wi::multiple_of_p (warg1, warg2, sgn, &quo))
 +    return wide_int_to_tree (TREE_TYPE (arg1), quo);
  
    return NULL_TREE; 
  }
@@@ -369,6 -357,8 +369,6 @@@ negate_mathfn_p (enum built_in_functio
  bool
  may_negate_without_overflow_p (const_tree t)
  {
 -  unsigned HOST_WIDE_INT val;
 -  unsigned int prec;
    tree type;
  
    gcc_assert (TREE_CODE (t) == INTEGER_CST);
    if (TYPE_UNSIGNED (type))
      return false;
  
 -  prec = TYPE_PRECISION (type);
 -  if (prec > HOST_BITS_PER_WIDE_INT)
 -    {
 -      if (TREE_INT_CST_LOW (t) != 0)
 -      return true;
 -      prec -= HOST_BITS_PER_WIDE_INT;
 -      val = TREE_INT_CST_HIGH (t);
 -    }
 -  else
 -    val = TREE_INT_CST_LOW (t);
 -  if (prec < HOST_BITS_PER_WIDE_INT)
 -    val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
 -  return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
 +  return !wi::only_sign_bit_p (t);
  }
  
  /* Determine whether an expression T can be cheaply negated using
@@@ -517,11 -519,13 +517,11 @@@ negate_expr_p (tree t
        break;
  
      case RSHIFT_EXPR:
 -      /* Optimize -((int)x >> 31) into (unsigned)x >> 31.  */
 +      /* Optimize -((int)x >> 31) into (unsigned)x >> 31 for int.  */
        if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
        {
          tree op1 = TREE_OPERAND (t, 1);
 -        if (TREE_INT_CST_HIGH (op1) == 0
 -            && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1)
 -               == TREE_INT_CST_LOW (op1))
 +        if (wi::eq_p (op1, TYPE_PRECISION (type) - 1))
            return true;
        }
        break;
@@@ -732,11 -736,13 +732,11 @@@ fold_negate_expr (location_t loc, tree 
        break;
  
      case RSHIFT_EXPR:
 -      /* Optimize -((int)x >> 31) into (unsigned)x >> 31.  */
 +      /* Optimize -((int)x >> 31) into (unsigned)x >> 31 for int.  */
        if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
        {
          tree op1 = TREE_OPERAND (t, 1);
 -        if (TREE_INT_CST_HIGH (op1) == 0
 -            && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1)
 -               == TREE_INT_CST_LOW (op1))
 +        if (wi::eq_p (op1, TYPE_PRECISION (type) - 1))
            {
              tree ntype = TYPE_UNSIGNED (type)
                           ? signed_type_for (type)
@@@ -966,154 -972,153 +966,154 @@@ int_binop_types_match_p (enum tree_cod
     to evaluate CODE at compile-time.  */
  
  static tree
 -int_const_binop_1 (enum tree_code code, const_tree arg1, const_tree arg2,
 +int_const_binop_1 (enum tree_code code, const_tree arg1, const_tree parg2,
                   int overflowable)
  {
 -  double_int op1, op2, res, tmp;
 +  wide_int res;
    tree t;
    tree type = TREE_TYPE (arg1);
 -  bool uns = TYPE_UNSIGNED (type);
 +  signop sign = TYPE_SIGN (type);
    bool overflow = false;
  
 -  op1 = tree_to_double_int (arg1);
 -  op2 = tree_to_double_int (arg2);
 +  wide_int arg2 = wide_int::from (parg2, TYPE_PRECISION (type),
 +                                TYPE_SIGN (TREE_TYPE (parg2)));
  
    switch (code)
      {
      case BIT_IOR_EXPR:
 -      res = op1 | op2;
 +      res = wi::bit_or (arg1, arg2);
        break;
  
      case BIT_XOR_EXPR:
 -      res = op1 ^ op2;
 +      res = wi::bit_xor (arg1, arg2);
        break;
  
      case BIT_AND_EXPR:
 -      res = op1 & op2;
 +      res = wi::bit_and (arg1, arg2);
        break;
  
      case RSHIFT_EXPR:
 -      res = op1.rshift (op2.to_shwi (), TYPE_PRECISION (type), !uns);
 -      break;
 -
      case LSHIFT_EXPR:
 -      /* It's unclear from the C standard whether shifts can overflow.
 -       The following code ignores overflow; perhaps a C standard
 -       interpretation ruling is needed.  */
 -      res = op1.lshift (op2.to_shwi (), TYPE_PRECISION (type), !uns);
 +      if (wi::neg_p (arg2))
 +      {
 +        arg2 = -arg2;
 +        if (code == RSHIFT_EXPR)
 +          code = LSHIFT_EXPR;
 +        else
 +          code = RSHIFT_EXPR;
 +      }
 +      
 +      if (code == RSHIFT_EXPR)
 +      /* It's unclear from the C standard whether shifts can overflow.
 +         The following code ignores overflow; perhaps a C standard
 +         interpretation ruling is needed.  */
 +      res = wi::rshift (arg1, arg2, sign,
 +                        SHIFT_COUNT_TRUNCATED
 +                        ? GET_MODE_BITSIZE (TYPE_MODE (type)) : 0);
 +      else
 +      res = wi::lshift (arg1, arg2,
 +                        SHIFT_COUNT_TRUNCATED
 +                        ? GET_MODE_BITSIZE (TYPE_MODE (type)) : 0);
        break;
 -
 +      
      case RROTATE_EXPR:
 -      res = op1.rrotate (op2.to_shwi (), TYPE_PRECISION (type));
 -      break;
 -
      case LROTATE_EXPR:
 -      res = op1.lrotate (op2.to_shwi (), TYPE_PRECISION (type));
 +      if (wi::neg_p (arg2))
 +      {
 +        arg2 = -arg2;
 +        if (code == RROTATE_EXPR)
 +          code = LROTATE_EXPR;
 +        else
 +          code = RROTATE_EXPR;
 +      }
 +      
 +      if (code == RROTATE_EXPR)
 +      res = wi::rrotate (arg1, arg2);
 +      else
 +      res = wi::lrotate (arg1, arg2);
        break;
  
      case PLUS_EXPR:
 -      res = op1.add_with_sign (op2, false, &overflow);
 +      res = wi::add (arg1, arg2, sign, &overflow);
        break;
  
      case MINUS_EXPR:
 -      res = op1.sub_with_overflow (op2, &overflow);
 +      res = wi::sub (arg1, arg2, sign, &overflow);
        break;
 -
 +      
      case MULT_EXPR:
 -      res = op1.mul_with_sign (op2, false, &overflow);
 +      res = wi::mul (arg1, arg2, sign, &overflow);
        break;
  
      case MULT_HIGHPART_EXPR:
 -      if (TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT)
 -      {
 -        bool dummy_overflow;
 -        if (TYPE_PRECISION (type) != 2 * HOST_BITS_PER_WIDE_INT)
 -          return NULL_TREE;
 -        op1.wide_mul_with_sign (op2, uns, &res, &dummy_overflow);
 -      }
 -      else
 -      {
 -        bool dummy_overflow;
 -        /* MULT_HIGHPART_EXPR can't ever oveflow, as the multiplication
 -           is performed in twice the precision of arguments.  */
 -        tmp = op1.mul_with_sign (op2, false, &dummy_overflow);
 -        res = tmp.rshift (TYPE_PRECISION (type),
 -                          2 * TYPE_PRECISION (type), !uns);
 -      }
 +      res = wi::mul_high (arg1, arg2, sign);
        break;
  
      case TRUNC_DIV_EXPR:
 -    case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
      case EXACT_DIV_EXPR:
 -      /* This is a shortcut for a common special case.  */
 -      if (op2.high == 0 && (HOST_WIDE_INT) op2.low > 0
 -        && !TREE_OVERFLOW (arg1)
 -        && !TREE_OVERFLOW (arg2)
 -        && op1.high == 0 && (HOST_WIDE_INT) op1.low >= 0)
 -      {
 -        if (code == CEIL_DIV_EXPR)
 -          op1.low += op2.low - 1;
 +      res = wi::div_trunc (arg1, arg2, sign, &overflow);
 +      if (overflow)
 +      return NULL_TREE;
 +      break;
  
 -        res.low = op1.low / op2.low, res.high = 0;
 -        break;
 -      }
 +    case FLOOR_DIV_EXPR:
 +      res = wi::div_floor (arg1, arg2, sign, &overflow);
 +      if (overflow)
 +      return NULL_TREE;
 +      break;
  
 -      /* ... fall through ...  */
 +    case CEIL_DIV_EXPR:
 +      res = wi::div_ceil (arg1, arg2, sign, &overflow);
 +      if (overflow)
 +      return NULL_TREE;
 +      break;
  
      case ROUND_DIV_EXPR:
 -      if (op2.is_zero ())
 +      res = wi::div_round (arg1, arg2, sign, &overflow);
 +      if (overflow)
        return NULL_TREE;
 -      if (op2.is_one ())
 -      {
 -        res = op1;
 -        break;
 -      }
 -      if (op1 == op2 && !op1.is_zero ())
 -      {
 -        res = double_int_one;
 -        break;
 -      }
 -      res = op1.divmod_with_overflow (op2, uns, code, &tmp, &overflow);
        break;
  
      case TRUNC_MOD_EXPR:
 -    case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
 -      /* This is a shortcut for a common special case.  */
 -      if (op2.high == 0 && (HOST_WIDE_INT) op2.low > 0
 -        && !TREE_OVERFLOW (arg1)
 -        && !TREE_OVERFLOW (arg2)
 -        && op1.high == 0 && (HOST_WIDE_INT) op1.low >= 0)
 -      {
 -        if (code == CEIL_MOD_EXPR)
 -          op1.low += op2.low - 1;
 -        res.low = op1.low % op2.low, res.high = 0;
 -        break;
 -      }
 +      res = wi::mod_trunc (arg1, arg2, sign, &overflow);
 +      if (overflow)
 +      return NULL_TREE;
 +      break;
  
 -      /* ... fall through ...  */
 +    case FLOOR_MOD_EXPR:
 +      res = wi::mod_floor (arg1, arg2, sign, &overflow);
 +      if (overflow)
 +      return NULL_TREE;
 +      break;
 +
 +    case CEIL_MOD_EXPR:
 +      res = wi::mod_ceil (arg1, arg2, sign, &overflow);
 +      if (overflow)
 +      return NULL_TREE;
 +      break;
  
      case ROUND_MOD_EXPR:
 -      if (op2.is_zero ())
 +      res = wi::mod_round (arg1, arg2, sign, &overflow);
 +      if (overflow)
        return NULL_TREE;
 -      tmp = op1.divmod_with_overflow (op2, uns, code, &res, &overflow);
        break;
  
      case MIN_EXPR:
 -      res = op1.min (op2, uns);
 +      res = wi::min (arg1, arg2, sign);
        break;
  
      case MAX_EXPR:
 -      res = op1.max (op2, uns);
 +      res = wi::max (arg1, arg2, sign);
        break;
  
      default:
        return NULL_TREE;
      }
  
 -  t = force_fit_type_double (TREE_TYPE (arg1), res, overflowable,
 -                           (!uns && overflow)
 -                           | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
 +  t = force_fit_type (type, res, overflowable,
 +                    (((sign == SIGNED || overflowable == -1)
 +                      && overflow)
 +                     | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (parg2)));
  
    return t;
  }
@@@ -1241,12 -1246,9 +1241,12 @@@ const_binop (enum tree_code code, tree 
  
        case LSHIFT_EXPR:
        case RSHIFT_EXPR:
 -        f2.data.high = TREE_INT_CST_HIGH (arg2);
 -        f2.data.low = TREE_INT_CST_LOW (arg2);
 -        f2.mode = SImode;
 +        {
 +          wide_int w2 = arg2;
 +          f2.data.high = w2.elt (1);
 +          f2.data.low = w2.elt (0);
 +          f2.mode = SImode;
 +        }
          break;
  
          default:
        if (code == VEC_LSHIFT_EXPR
          || code == VEC_RSHIFT_EXPR)
        {
 -        if (!host_integerp (arg2, 1))
 +        if (!tree_fits_uhwi_p (arg2))
            return NULL_TREE;
  
 -        unsigned HOST_WIDE_INT shiftc = tree_low_cst (arg2, 1);
 -        unsigned HOST_WIDE_INT outerc = tree_low_cst (TYPE_SIZE (type), 1);
 +        unsigned HOST_WIDE_INT shiftc = tree_to_uhwi (arg2);
 +        unsigned HOST_WIDE_INT outerc = tree_to_uhwi (TYPE_SIZE (type));
          unsigned HOST_WIDE_INT innerc
 -          = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
 +          = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
          if (shiftc >= outerc || (shiftc % innerc) != 0)
            return NULL_TREE;
          int offset = shiftc / innerc;
@@@ -1581,12 -1583,18 +1581,12 @@@ size_diffop_loc (location_t loc, tree a
  static tree
  fold_convert_const_int_from_int (tree type, const_tree arg1)
  {
 -  tree t;
 -
    /* Given an integer constant, make new constant with new type,
 -     appropriately sign-extended or truncated.  */
 -  t = force_fit_type_double (type, tree_to_double_int (arg1),
 -                           !POINTER_TYPE_P (TREE_TYPE (arg1)),
 -                           (TREE_INT_CST_HIGH (arg1) < 0
 -                            && (TYPE_UNSIGNED (type)
 -                                < TYPE_UNSIGNED (TREE_TYPE (arg1))))
 -                           | TREE_OVERFLOW (arg1));
 -
 -  return t;
 +     appropriately sign-extended or truncated.  Use widest_int
 +     so that any extension is done according ARG1's type.  */
 +  return force_fit_type (type, wi::to_widest (arg1),
 +                       !POINTER_TYPE_P (TREE_TYPE (arg1)),
 +                       TREE_OVERFLOW (arg1));
  }
  
  /* A subroutine of fold_convert_const handling conversions a REAL_CST
  static tree
  fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg1)
  {
 -  int overflow = 0;
 +  bool overflow = false;
    tree t;
  
    /* The following code implements the floating point to integer
       C and C++ standards that simply state that the behavior of
       FP-to-integer conversion is unspecified upon overflow.  */
  
 -  double_int val;
 +  wide_int val;
    REAL_VALUE_TYPE r;
    REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
  
    /* If R is NaN, return zero and show we have an overflow.  */
    if (REAL_VALUE_ISNAN (r))
      {
 -      overflow = 1;
 -      val = double_int_zero;
 +      overflow = true;
 +      val = wi::zero (TYPE_PRECISION (type));
      }
  
    /* See if R is less than the lower bound or greater than the
        REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
        if (REAL_VALUES_LESS (r, l))
        {
 -        overflow = 1;
 -        val = tree_to_double_int (lt);
 +        overflow = true;
 +        val = lt;
        }
      }
  
          REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
          if (REAL_VALUES_LESS (u, r))
            {
 -            overflow = 1;
 -            val = tree_to_double_int (ut);
 +            overflow = true;
 +            val = ut;
            }
        }
      }
  
    if (! overflow)
 -    real_to_integer2 ((HOST_WIDE_INT *) &val.low, &val.high, &r);
 +    val = real_to_integer (&r, &overflow, TYPE_PRECISION (type));
  
 -  t = force_fit_type_double (type, val, -1, overflow | TREE_OVERFLOW (arg1));
 +  t = force_fit_type (type, val, -1, overflow | TREE_OVERFLOW (arg1));
    return t;
  }
  
@@@ -1702,12 -1710,12 +1702,12 @@@ fold_convert_const_int_from_fixed (tre
  
    /* Given a fixed-point constant, make new constant with new type,
       appropriately sign-extended or truncated.  */
 -  t = force_fit_type_double (type, temp, -1,
 -                           (temp.is_negative ()
 -                            && (TYPE_UNSIGNED (type)
 -                                < TYPE_UNSIGNED (TREE_TYPE (arg1))))
 -                           | TREE_OVERFLOW (arg1));
 -
 +  t = force_fit_type (type, temp, -1,
 +                    (temp.is_negative ()
 +                     && (TYPE_UNSIGNED (type)
 +                         < TYPE_UNSIGNED (TREE_TYPE (arg1))))
 +                    | TREE_OVERFLOW (arg1));
 +  
    return t;
  }
  
@@@ -1789,18 -1797,9 +1789,18 @@@ fold_convert_const_fixed_from_int (tre
    FIXED_VALUE_TYPE value;
    tree t;
    bool overflow_p;
 +  double_int di;
 +
 +  gcc_assert (TREE_INT_CST_NUNITS (arg1) <= 2);
 +
 +  di.low = TREE_INT_CST_ELT (arg1, 0);
 +  if (TREE_INT_CST_NUNITS (arg1) == 1)
 +    di.high = (HOST_WIDE_INT)di.low < 0 ? (HOST_WIDE_INT)-1 : 0; 
 +  else 
 +    di.high = TREE_INT_CST_ELT (arg1, 1);
  
    overflow_p = fixed_convert_from_int (&value, TYPE_MODE (type),
 -                                     TREE_INT_CST (arg1),
 +                                     di,
                                       TYPE_UNSIGNED (TREE_TYPE (arg1)),
                                       TYPE_SATURATING (type));
    t = build_fixed (type, value);
@@@ -2716,10 -2715,11 +2716,11 @@@ operand_equal_p (const_tree arg0, const
        case COMPONENT_REF:
          /* Handle operand 2 the same as for ARRAY_REF.  Operand 0
             may be NULL when we're called to compare MEM_EXPRs.  */
-         if (!OP_SAME_WITH_NULL (0))
+         if (!OP_SAME_WITH_NULL (0)
+             || !OP_SAME (1))
            return 0;
          flags &= ~OEP_CONSTANT_ADDRESS_OF;
-         return OP_SAME (1) && OP_SAME_WITH_NULL (2);
+         return OP_SAME_WITH_NULL (2);
  
        case BIT_FIELD_REF:
          if (!OP_SAME (0))
@@@ -3419,8 -3419,8 +3420,8 @@@ make_bit_field_ref (location_t loc, tre
        tree size = TYPE_SIZE (TREE_TYPE (inner));
        if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
           || POINTER_TYPE_P (TREE_TYPE (inner)))
 -        && host_integerp (size, 0)
 -        && tree_low_cst (size, 0) == bitsize)
 +        && tree_fits_shwi_p (size)
 +        && tree_to_shwi (size) == bitsize)
        return fold_convert_loc (loc, type, inner);
      }
  
@@@ -3473,11 -3473,6 +3474,6 @@@ optimize_bit_field_compare (location_t 
    tree mask;
    tree offset;
  
-   /* In the strict volatile bitfields case, doing code changes here may prevent
-      other optimizations, in particular in a SLOW_BYTE_ACCESS setting.  */
-   if (flag_strict_volatile_bitfields > 0)
-     return 0;
    /* Get all the information about the extractions being done.  If the bit size
       if the same as the size of the underlying object, we aren't doing an
       extraction at all and so can do nothing.  We also don't want to
    linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
                                &lunsignedp, &lvolatilep, false);
    if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
-       || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR)
+       || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep)
      return 0;
  
   if (!const_p)
  
       if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
         || lunsignedp != runsignedp || offset != 0
-        || TREE_CODE (rinner) == PLACEHOLDER_EXPR)
+        || TREE_CODE (rinner) == PLACEHOLDER_EXPR || rvolatilep)
         return 0;
     }
  
    /* See if we can find a mode to refer to this field.  We should be able to,
       but fail if we can't.  */
-   if (lvolatilep
-       && GET_MODE_BITSIZE (lmode) > 0
-       && flag_strict_volatile_bitfields > 0)
-     nmode = lmode;
-   else
-     nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
-                          const_p ? TYPE_ALIGN (TREE_TYPE (linner))
-                          : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
-                                 TYPE_ALIGN (TREE_TYPE (rinner))),
-                          word_mode, lvolatilep || rvolatilep);
+   nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
+                        const_p ? TYPE_ALIGN (TREE_TYPE (linner))
+                        : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
+                               TYPE_ALIGN (TREE_TYPE (rinner))),
+                        word_mode, false);
    if (nmode == VOIDmode)
      return 0;
  
       appropriate number of bits and mask it with the computed mask
       (in case this was a signed field).  If we changed it, make a new one.  */
    lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1);
-   if (lvolatilep)
-     {
-       TREE_SIDE_EFFECTS (lhs) = 1;
-       TREE_THIS_VOLATILE (lhs) = 1;
-     }
  
    rhs = const_binop (BIT_AND_EXPR,
                     const_binop (LSHIFT_EXPR,
@@@ -3710,24 -3695,23 +3696,24 @@@ decode_field_reference (location_t loc
  }
  
  /* Return nonzero if MASK represents a mask of SIZE ones in the low-order
 -   bit positions.  */
 +   bit positions and MASK is SIGNED.  */
  
  static int
 -all_ones_mask_p (const_tree mask, int size)
 +all_ones_mask_p (const_tree mask, unsigned int size)
  {
    tree type = TREE_TYPE (mask);
    unsigned int precision = TYPE_PRECISION (type);
 -  tree tmask;
  
 -  tmask = build_int_cst_type (signed_type_for (type), -1);
 +  /* If this function returns true when the type of the mask is
 +     UNSIGNED, then there will be errors.  In particular see
 +     gcc.c-torture/execute/990326-1.c.  There does not appear to be
 +     any documentation paper trail as to why this is so.  But the pre
 +     wide-int worked with that restriction and it has been preserved
 +     here.  */
 +  if (size > precision || TYPE_SIGN (type) == UNSIGNED)
 +    return false;
  
 -  return
 -    tree_int_cst_equal (mask,
 -                      const_binop (RSHIFT_EXPR,
 -                                   const_binop (LSHIFT_EXPR, tmask,
 -                                                size_int (precision - size)),
 -                                   size_int (precision - size)));
 +  return wi::mask (size, false, precision) == mask;
  }
  
  /* Subroutine for fold: determine if VAL is the INTEGER_CONST that
  static tree
  sign_bit_p (tree exp, const_tree val)
  {
 -  unsigned HOST_WIDE_INT mask_lo, lo;
 -  HOST_WIDE_INT mask_hi, hi;
    int width;
    tree t;
  
      return NULL_TREE;
  
    width = TYPE_PRECISION (t);
 -  if (width > HOST_BITS_PER_WIDE_INT)
 -    {
 -      hi = (unsigned HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT - 1);
 -      lo = 0;
 -
 -      mask_hi = (HOST_WIDE_INT_M1U >> (HOST_BITS_PER_DOUBLE_INT - width));
 -      mask_lo = -1;
 -    }
 -  else
 -    {
 -      hi = 0;
 -      lo = (unsigned HOST_WIDE_INT) 1 << (width - 1);
 -
 -      mask_hi = 0;
 -      mask_lo = (HOST_WIDE_INT_M1U >> (HOST_BITS_PER_WIDE_INT - width));
 -    }
 -
 -  /* We mask off those bits beyond TREE_TYPE (exp) so that we can
 -     treat VAL as if it were unsigned.  */
 -  if ((TREE_INT_CST_HIGH (val) & mask_hi) == hi
 -      && (TREE_INT_CST_LOW (val) & mask_lo) == lo)
 +  if (wi::only_sign_bit_p (val, width))
      return exp;
  
    /* Handle extension from a narrower type.  */
@@@ -3998,7 -4004,7 +3984,7 @@@ make_range_step (location_t loc, enum t
            {
              in_p = ! in_p;
              high = range_binop (MINUS_EXPR, NULL_TREE, low, 0,
 -                                integer_one_node, 0);
 +                                build_int_cst (TREE_TYPE (low), 1), 0);
              low = build_int_cst (arg0_type, 0);
            }
        }
        if (n_low && n_high && tree_int_cst_lt (n_high, n_low))
          {
            low = range_binop (PLUS_EXPR, arg0_type, n_high, 0,
 -                             integer_one_node, 0);
 +                             build_int_cst (TREE_TYPE (n_high), 1), 0);
            high = range_binop (MINUS_EXPR, arg0_type, n_low, 0,
 -                              integer_one_node, 0);
 +                              build_int_cst (TREE_TYPE (n_low), 1), 0);
  
            /* If the range is of the form +/- [ x+1, x ], we won't
               be able to normalize it.  But then, it represents the
@@@ -4308,10 -4314,23 +4294,10 @@@ build_range_check (location_t loc, tre
    /* Optimize (c>=1) && (c<=127) into (signed char)c > 0.  */
    if (integer_onep (low) && TREE_CODE (high) == INTEGER_CST)
      {
 -      unsigned HOST_WIDE_INT lo;
 -      HOST_WIDE_INT hi;
 -      int prec;
 +      int prec = TYPE_PRECISION (etype);
 +      wide_int osb = wi::set_bit_in_zero (prec - 1, prec) - 1;
  
 -      prec = TYPE_PRECISION (etype);
 -      if (prec <= HOST_BITS_PER_WIDE_INT)
 -      {
 -        hi = 0;
 -        lo = ((unsigned HOST_WIDE_INT) 1 << (prec - 1)) - 1;
 -      }
 -      else
 -      {
 -        hi = ((HOST_WIDE_INT) 1 << (prec - HOST_BITS_PER_WIDE_INT - 1)) - 1;
 -        lo = HOST_WIDE_INT_M1U;
 -      }
 -
 -      if (TREE_INT_CST_HIGH (high) == hi && TREE_INT_CST_LOW (high) == lo)
 +      if (osb == high)
        {
          if (TYPE_UNSIGNED (etype))
            {
        utype = unsigned_type_for (etype);
        maxv = fold_convert_loc (loc, utype, TYPE_MAX_VALUE (etype));
        maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
 -                        integer_one_node, 1);
 +                        build_int_cst (TREE_TYPE (maxv), 1), 1);
        minv = fold_convert_loc (loc, utype, TYPE_MIN_VALUE (etype));
  
        if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
@@@ -4393,8 -4412,7 +4379,8 @@@ range_predecessor (tree val
        && operand_equal_p (val, TYPE_MIN_VALUE (type), 0))
      return 0;
    else
 -    return range_binop (MINUS_EXPR, NULL_TREE, val, 0, integer_one_node, 0);
 +    return range_binop (MINUS_EXPR, NULL_TREE, val, 0, 
 +                      build_int_cst (TREE_TYPE (val), 1), 0);
  }
  
  /* Return the successor of VAL in its type, handling the infinite case.  */
@@@ -4408,8 -4426,7 +4394,8 @@@ range_successor (tree val
        && operand_equal_p (val, TYPE_MAX_VALUE (type), 0))
      return 0;
    else
 -    return range_binop (PLUS_EXPR, NULL_TREE, val, 0, integer_one_node, 0);
 +    return range_binop (PLUS_EXPR, NULL_TREE, val, 0, 
 +                      build_int_cst (TREE_TYPE (val), 1), 0);
  }
  
  /* Given two ranges, see if we can merge them into one.  Return 1 if we
@@@ -4589,8 -4606,7 +4575,8 @@@ merge_ranges (int *pin_p, tree *plow, t
                    if (TYPE_UNSIGNED (TREE_TYPE (high1))
                        && integer_zerop (range_binop (PLUS_EXPR, NULL_TREE,
                                                       high1, 1,
 -                                                     integer_one_node, 1)))
 +                                                     build_int_cst (TREE_TYPE (high1), 1),
 +                                                     1)))
                      high1 = 0;
                    break;
                  default:
@@@ -4954,12 -4970,16 +4940,16 @@@ fold_range_test (location_t loc, enum t
    int in0_p, in1_p, in_p;
    tree low0, low1, low, high0, high1, high;
    bool strict_overflow_p = false;
-   tree lhs = make_range (op0, &in0_p, &low0, &high0, &strict_overflow_p);
-   tree rhs = make_range (op1, &in1_p, &low1, &high1, &strict_overflow_p);
-   tree tem;
+   tree tem, lhs, rhs;
    const char * const warnmsg = G_("assuming signed overflow does not occur "
                                  "when simplifying range test");
  
+   if (!INTEGRAL_TYPE_P (type))
+     return 0;
+   lhs = make_range (op0, &in0_p, &low0, &high0, &strict_overflow_p);
+   rhs = make_range (op1, &in1_p, &low1, &high1, &strict_overflow_p);
    /* If this is an OR operation, invert both sides; we will invert
       again at the end.  */
    if (or_op)
@@@ -5042,7 -5062,8 +5032,7 @@@ unextend (tree c, int p, int unsignedp
    /* We work by getting just the sign bit into the low-order bit, then
       into the high-order bit, then sign-extend.  We then XOR that value
       with C.  */
 -  temp = const_binop (RSHIFT_EXPR, c, size_int (p - 1));
 -  temp = const_binop (BIT_AND_EXPR, temp, size_int (1));
 +  temp = build_int_cst (TREE_TYPE (c), wi::extract_uhwi (c, p - 1, 1));
  
    /* We must use a signed type in order to get an arithmetic right shift.
       However, we must also avoid introducing accidental overflows, so that
@@@ -5848,7 -5869,8 +5838,7 @@@ extract_muldiv_1 (tree t, tree c, enum 
          && (tcode == RSHIFT_EXPR || TYPE_UNSIGNED (TREE_TYPE (op0)))
          /* const_binop may not detect overflow correctly,
             so check for it explicitly here.  */
 -        && TYPE_PRECISION (TREE_TYPE (size_one_node)) > TREE_INT_CST_LOW (op1)
 -        && TREE_INT_CST_HIGH (op1) == 0
 +        && wi::gtu_p (TYPE_PRECISION (TREE_TYPE (size_one_node)), op1)
          && 0 != (t1 = fold_convert (ctype,
                                      const_binop (LSHIFT_EXPR,
                                                   size_one_node,
         assuming no overflow.  */
        if (tcode == code)
        {
 -        double_int mul;
          bool overflow_p;
 -        unsigned prec = TYPE_PRECISION (ctype);
 -        bool uns = TYPE_UNSIGNED (ctype);
 -        double_int diop1 = tree_to_double_int (op1).ext (prec, uns);
 -        double_int dic = tree_to_double_int (c).ext (prec, uns);
 -        mul = diop1.mul_with_sign (dic, false, &overflow_p);
 -        overflow_p = ((!uns && overflow_p)
 -                      | TREE_OVERFLOW (c) | TREE_OVERFLOW (op1));
 -        if (!double_int_fits_to_tree_p (ctype, mul)
 -            && ((uns && tcode != MULT_EXPR) || !uns))
 -          overflow_p = 1;
 +        signop sign = TYPE_SIGN (ctype);
 +        wide_int mul = wi::mul_full (op1, c, sign);
 +        overflow_p = TREE_OVERFLOW (c) | TREE_OVERFLOW (op1);
 +        if (!wi::fits_to_tree_p (mul, ctype)
 +            && ((sign == UNSIGNED && tcode != MULT_EXPR) || sign == SIGNED))
 +          overflow_p = true;
          if (!overflow_p)
            return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
 -                              double_int_to_tree (ctype, mul));
 +                              wide_int_to_tree (ctype, mul));
        }
  
        /* If these operations "cancel" each other, we have the main
@@@ -6402,26 -6429,29 +6392,26 @@@ fold_div_compare (location_t loc
    tree prod, tmp, hi, lo;
    tree arg00 = TREE_OPERAND (arg0, 0);
    tree arg01 = TREE_OPERAND (arg0, 1);
 -  double_int val;
 -  bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
 -  bool neg_overflow;
 +  signop sign  = TYPE_SIGN (TREE_TYPE (arg0));
 +  bool neg_overflow = false;
    bool overflow;
  
    /* We have to do this the hard way to detect unsigned overflow.
       prod = int_const_binop (MULT_EXPR, arg01, arg1);  */
 -  val = TREE_INT_CST (arg01)
 -      .mul_with_sign (TREE_INT_CST (arg1), unsigned_p, &overflow);
 -  prod = force_fit_type_double (TREE_TYPE (arg00), val, -1, overflow);
 +  wide_int val = wi::mul (arg01, arg1, sign, &overflow);
 +  prod = force_fit_type (TREE_TYPE (arg00), val, -1, overflow);
    neg_overflow = false;
  
 -  if (unsigned_p)
 +  if (sign == UNSIGNED)
      {
        tmp = int_const_binop (MINUS_EXPR, arg01,
                               build_int_cst (TREE_TYPE (arg01), 1));
        lo = prod;
  
        /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp).  */
 -      val = TREE_INT_CST (prod)
 -          .add_with_sign (TREE_INT_CST (tmp), unsigned_p, &overflow);
 -      hi = force_fit_type_double (TREE_TYPE (arg00), val,
 -                                -1, overflow | TREE_OVERFLOW (prod));
 +      val = wi::add (prod, tmp, sign, &overflow);
 +      hi = force_fit_type (TREE_TYPE (arg00), val,
 +                         -1, overflow | TREE_OVERFLOW (prod));
      }
    else if (tree_int_cst_sgn (arg01) >= 0)
      {
@@@ -6612,10 -6642,12 +6602,10 @@@ fold_single_bit_test (location_t loc, e
         not overflow, adjust BITNUM and INNER.  */
        if (TREE_CODE (inner) == RSHIFT_EXPR
          && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST
 -        && host_integerp (TREE_OPERAND (inner, 1), 1)
 -        && bitnum < TYPE_PRECISION (type)
 -        && (TREE_INT_CST_LOW (TREE_OPERAND (inner, 1))
 -            < (unsigned) (TYPE_PRECISION (type) - bitnum)))
 +        && wi::ltu_p (wi::to_widest (TREE_OPERAND (inner, 1)) + bitnum,
 +                      TYPE_PRECISION (type)))
        {
 -        bitnum += TREE_INT_CST_LOW (TREE_OPERAND (inner, 1));
 +        bitnum += tree_to_hwi (TREE_OPERAND (inner, 1));
          inner = TREE_OPERAND (inner, 0);
        }
  
@@@ -6873,8 -6905,8 +6863,8 @@@ fold_sign_changed_comparison (location_
      return NULL_TREE;
  
    if (TREE_CODE (arg1) == INTEGER_CST)
 -    arg1 = force_fit_type_double (inner_type, tree_to_double_int (arg1),
 -                                0, TREE_OVERFLOW (arg1));
 +    arg1 = force_fit_type (inner_type, wi::to_widest (arg1), 0,
 +                         TREE_OVERFLOW (arg1));
    else
      arg1 = fold_convert_loc (loc, inner_type, arg1);
  
@@@ -6962,7 -6994,7 +6952,7 @@@ try_move_mult_to_index (location_t loc
        else
        {
          /* Try if delta is a multiple of step.  */
 -        tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, op1, step);
 +        tree tmp = div_if_zero_remainder (op1, step);
          if (! tmp)
            goto cont;
          delta = tmp;
@@@ -7034,7 -7066,7 +7024,7 @@@ cont
          else
            {
              /* Try if delta is a multiple of step.  */
 -            tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, op1, step);
 +            tree tmp = div_if_zero_remainder (op1, step);
              if (! tmp)
                continue;
              delta = tmp;
@@@ -7190,8 -7222,7 +7180,8 @@@ fold_plusminus_mult_expr (location_t lo
        arg10 = build_one_cst (type);
        /* As we canonicalize A - 2 to A + -2 get rid of that sign for
         the purpose of this canonicalization.  */
 -      if (TREE_INT_CST_HIGH (arg1) == -1
 +      if (TYPE_SIGN (TREE_TYPE (arg1)) == SIGNED
 +        && wi::neg_p (arg1)
          && negate_expr_p (arg1)
          && code == PLUS_EXPR)
        {
    /* No identical multiplicands; see if we can find a common
       power-of-two factor in non-power-of-two multiplies.  This
       can help in multi-dimensional array access.  */
 -  else if (host_integerp (arg01, 0)
 -         && host_integerp (arg11, 0))
 +  else if (tree_fits_shwi_p (arg01)
 +         && tree_fits_shwi_p (arg11))
      {
        HOST_WIDE_INT int01, int11, tmp;
        bool swap = false;
        tree maybe_same;
 -      int01 = TREE_INT_CST_LOW (arg01);
 -      int11 = TREE_INT_CST_LOW (arg11);
 +      int01 = tree_to_shwi (arg01);
 +      int11 = tree_to_shwi (arg11);
  
        /* Move min of absolute values to int11.  */
        if (absu_hwi (int01) < absu_hwi (int11))
@@@ -7289,9 -7320,11 +7279,9 @@@ native_encode_int (const_tree expr, uns
    for (byte = 0; byte < total_bytes; byte++)
      {
        int bitpos = byte * BITS_PER_UNIT;
 -      if (bitpos < HOST_BITS_PER_WIDE_INT)
 -      value = (unsigned char) (TREE_INT_CST_LOW (expr) >> bitpos);
 -      else
 -      value = (unsigned char) (TREE_INT_CST_HIGH (expr)
 -                               >> (bitpos - HOST_BITS_PER_WIDE_INT));
 +      /* Extend EXPR according to TYPE_SIGN if the precision isn't a whole
 +       number of bytes.  */
 +      value = wi::extract_uhwi (wi::to_widest (expr), bitpos, BITS_PER_UNIT);
  
        if (total_bytes > UNITS_PER_WORD)
        {
@@@ -7454,9 -7487,9 +7444,9 @@@ native_encode_string (const_tree expr, 
    if (TREE_CODE (type) != ARRAY_TYPE
        || TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE
        || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type))) != BITS_PER_UNIT
 -      || !host_integerp (TYPE_SIZE_UNIT (type), 0))
 +      || !tree_fits_shwi_p (TYPE_SIZE_UNIT (type)))
      return 0;
 -  total_bytes = tree_low_cst (TYPE_SIZE_UNIT (type), 0);
 +  total_bytes = tree_to_shwi (TYPE_SIZE_UNIT (type));
    if (total_bytes > len)
      return 0;
    if (TREE_STRING_LENGTH (expr) < total_bytes)
@@@ -7513,14 -7546,15 +7503,14 @@@ static tre
  native_interpret_int (tree type, const unsigned char *ptr, int len)
  {
    int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
 -  double_int result;
  
    if (total_bytes > len
        || total_bytes * BITS_PER_UNIT > HOST_BITS_PER_DOUBLE_INT)
      return NULL_TREE;
  
 -  result = double_int::from_buffer (ptr, total_bytes);
 +  wide_int result = wi::from_buffer (ptr, total_bytes);
  
 -  return double_int_to_tree (type, result);
 +  return wide_int_to_tree (type, result);
  }
  
  
@@@ -8063,11 -8097,11 +8053,11 @@@ fold_unary_loc (location_t loc, enum tr
            change = 1;
          else if (TYPE_PRECISION (TREE_TYPE (and1))
                   <= HOST_BITS_PER_WIDE_INT
 -                 && host_integerp (and1, 1))
 +                 && tree_fits_uhwi_p (and1))
            {
              unsigned HOST_WIDE_INT cst;
  
 -            cst = tree_low_cst (and1, 1);
 +            cst = tree_to_uhwi (and1);
              cst &= HOST_WIDE_INT_M1U
                     << (TYPE_PRECISION (TREE_TYPE (and1)) - 1);
              change = (cst == 0);
            }
          if (change)
            {
 -            tem = force_fit_type_double (type, tree_to_double_int (and1),
 -                                         0, TREE_OVERFLOW (and1));
 +            tem = force_fit_type (type, wi::to_widest (and1), 0,
 +                                  TREE_OVERFLOW (and1));
              return fold_build2_loc (loc, BIT_AND_EXPR, type,
 -                                fold_convert_loc (loc, type, and0), tem);
 +                                    fold_convert_loc (loc, type, and0), tem);
            }
        }
  
@@@ -8868,28 -8902,28 +8858,28 @@@ maybe_canonicalize_comparison (location
  static bool
  pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
  {
 -  double_int di_offset, total;
 -
    if (!POINTER_TYPE_P (TREE_TYPE (base)))
      return true;
  
    if (bitpos < 0)
      return true;
  
 +  wide_int wi_offset;
 +  int precision = TYPE_PRECISION (TREE_TYPE (base));
    if (offset == NULL_TREE)
 -    di_offset = double_int_zero;
 +    wi_offset = wi::zero (precision);
    else if (TREE_CODE (offset) != INTEGER_CST || TREE_OVERFLOW (offset))
      return true;
    else
 -    di_offset = TREE_INT_CST (offset);
 +    wi_offset = offset;
  
    bool overflow;
 -  double_int units = double_int::from_uhwi (bitpos / BITS_PER_UNIT);
 -  total = di_offset.add_with_sign (units, true, &overflow);
 +  wide_int units = wi::shwi (bitpos / BITS_PER_UNIT, precision);
 +  wide_int total = wi::add (wi_offset, units, UNSIGNED, &overflow);
    if (overflow)
      return true;
  
 -  if (total.high != 0)
 +  if (!wi::fits_uhwi_p (total))
      return true;
  
    HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (TREE_TYPE (base)));
        size = base_size;
      }
  
 -  return total.low > (unsigned HOST_WIDE_INT) size;
 +  return total.to_uhwi () > (unsigned HOST_WIDE_INT) size;
  }
  
  /* Subroutine of fold_binary.  This routine performs all of the
@@@ -9043,7 -9077,7 +9033,7 @@@ fold_comparison (location_t loc, enum t
              indirect_base0 = true;
            }
          offset0 = TREE_OPERAND (arg0, 1);
 -        if (host_integerp (offset0, 0))
 +        if (tree_fits_shwi_p (offset0))
            {
              HOST_WIDE_INT off = size_low_cst (offset0);
              if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off)
              indirect_base1 = true;
            }
          offset1 = TREE_OPERAND (arg1, 1);
 -        if (host_integerp (offset1, 0))
 +        if (tree_fits_shwi_p (offset1))
            {
              HOST_WIDE_INT off = size_low_cst (offset1);
              if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off)
@@@ -9715,7 -9749,7 +9705,7 @@@ get_pointer_modulus_and_residue (tree e
        inner_code = TREE_CODE (op1);
        if (inner_code == INTEGER_CST)
        {
 -        *residue += TREE_INT_CST_LOW (op1);
 +        *residue += tree_to_hwi (op1);
          return modulus;
        }
        else if (inner_code == MULT_EXPR)
              unsigned HOST_WIDE_INT align;
  
              /* Compute the greatest power-of-2 divisor of op1.  */
 -            align = TREE_INT_CST_LOW (op1);
 +            align = tree_to_hwi (op1);
              align &= -align;
  
              /* If align is non-zero and less than *modulus, replace
@@@ -9901,12 -9935,19 +9891,12 @@@ exact_inverse (tree type, tree cst
  
  /*  Mask out the tz least significant bits of X of type TYPE where
      tz is the number of trailing zeroes in Y.  */
 -static double_int
 -mask_with_tz (tree type, double_int x, double_int y)
 +static wide_int
 +mask_with_tz (tree type, wide_int x, wide_int y)
  {
 -  int tz = y.trailing_zeros ();
 -
 +  int tz = wi::ctz (y);
    if (tz > 0)
 -    {
 -      double_int mask;
 -
 -      mask = ~double_int::mask (tz);
 -      mask = mask.ext (TYPE_PRECISION (type), TYPE_UNSIGNED (type));
 -      return mask & x;
 -    }
 +    return wi::mask (tz, true, TYPE_PRECISION (type)) & x;
    return x;
  }
  
@@@ -10448,7 -10489,9 +10438,7 @@@ fold_binary_loc (location_t loc
            code11 = TREE_CODE (tree11);
            if (code01 == INTEGER_CST
                && code11 == INTEGER_CST
 -              && TREE_INT_CST_HIGH (tree01) == 0
 -              && TREE_INT_CST_HIGH (tree11) == 0
 -              && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
 +              && (wi::to_widest (tree01) + wi::to_widest (tree11)
                    == element_precision (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
              {
                tem = build2_loc (loc, LROTATE_EXPR,
                                fold_build2_loc (loc, MULT_EXPR, type,
                                             build_int_cst (type, 2) , arg1));
  
+         /* ((T) (X /[ex] C)) * C cancels out if the conversion is
+            sign-changing only.  */
+         if (TREE_CODE (arg1) == INTEGER_CST
+             && TREE_CODE (arg0) == EXACT_DIV_EXPR
+             && operand_equal_p (arg1, TREE_OPERAND (arg0, 1), 0))
+           return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
          strict_overflow_p = false;
          if (TREE_CODE (arg1) == INTEGER_CST
              && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE,
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
 -        double_int c1, c2, c3, msk;
          int width = TYPE_PRECISION (type), w;
          bool try_simplify = true;
 -
 -        c1 = tree_to_double_int (TREE_OPERAND (arg0, 1));
 -        c2 = tree_to_double_int (arg1);
 +        wide_int c1 = TREE_OPERAND (arg0, 1);
 +        wide_int c2 = arg1;
  
          /* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2).  */
          if ((c1 & c2) == c1)
            return omit_one_operand_loc (loc, type, arg1,
                                         TREE_OPERAND (arg0, 0));
  
 -        msk = double_int::mask (width);
 +        wide_int msk = wi::mask (width, false,
 +                                 TYPE_PRECISION (TREE_TYPE (arg1)));
  
          /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2.  */
 -        if (msk.and_not (c1 | c2).is_zero ())
 +        if (msk.and_not (c1 | c2) == 0)
            return fold_build2_loc (loc, BIT_IOR_EXPR, type,
                                    TREE_OPERAND (arg0, 0), arg1);
  
             mode which allows further optimizations.  */
          c1 &= msk;
          c2 &= msk;
 -        c3 = c1.and_not (c2);
 -        for (w = BITS_PER_UNIT;
 -             w <= width && w <= HOST_BITS_PER_WIDE_INT;
 -             w <<= 1)
 +        wide_int c3 = c1.and_not (c2);
 +        for (w = BITS_PER_UNIT; w <= width; w <<= 1)
            {
 -            unsigned HOST_WIDE_INT mask
 -              = HOST_WIDE_INT_M1U >> (HOST_BITS_PER_WIDE_INT - w);
 -            if (((c1.low | c2.low) & mask) == mask
 -                && (c1.low & ~mask) == 0 && c1.high == 0)
 +            wide_int mask = wi::mask (width - w, false,
 +                                      TYPE_PRECISION (type));
 +            if (((c1 | c2) & mask) == mask && c1.and_not (mask) == 0)
                {
 -                c3 = double_int::from_uhwi (mask);
 +                c3 = mask;
                  break;
                }
            }
                            == INTEGER_CST)
          {
            tree t = TREE_OPERAND (TREE_OPERAND (arg0, 0), 1);
 -          double_int masked = mask_with_tz (type, c3, tree_to_double_int (t));
 +          wide_int masked = mask_with_tz (type, c3, t);
  
            try_simplify = (masked != c1);
          }
            return fold_build2_loc (loc, BIT_IOR_EXPR, type,
                                    fold_build2_loc (loc, BIT_AND_EXPR, type,
                                                     TREE_OPERAND (arg0, 0),
 -                                                   double_int_to_tree (type,
 -                                                                       c3)),
 +                                                   wide_int_to_tree (type,
 +                                                                     c3)),
                                    arg1);
        }
  
           multiple of 1 << CST.  */
        if (TREE_CODE (arg1) == INTEGER_CST)
        {
 -        double_int cst1 = tree_to_double_int (arg1);
 -        double_int ncst1 = (-cst1).ext (TYPE_PRECISION (TREE_TYPE (arg1)),
 -                                        TYPE_UNSIGNED (TREE_TYPE (arg1)));
 +        wide_int cst1 = arg1;
 +        wide_int ncst1 = -cst1;
          if ((cst1 & ncst1) == ncst1
              && multiple_of_p (type, arg0,
 -                              double_int_to_tree (TREE_TYPE (arg1), ncst1)))
 +                              wide_int_to_tree (TREE_TYPE (arg1), ncst1)))
            return fold_convert_loc (loc, type, arg0);
        }
  
          && TREE_CODE (arg0) == MULT_EXPR
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
 -        double_int masked
 -          = mask_with_tz (type, tree_to_double_int (arg1),
 -                          tree_to_double_int (TREE_OPERAND (arg0, 1)));
 +        wide_int masked = mask_with_tz (type, arg1, TREE_OPERAND (arg0, 1));
  
 -        if (masked.is_zero ())
 +        if (masked == 0)
            return omit_two_operands_loc (loc, type, build_zero_cst (type),
                                          arg0, arg1);
 -        else if (masked != tree_to_double_int (arg1))
 +        else if (masked != arg1)
            return fold_build2_loc (loc, code, type, op0,
 -                                  double_int_to_tree (type, masked));
 +                                  wide_int_to_tree (type, masked));
        }
  
        /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
         and for - instead of + (or unary - instead of +)
         and/or ^ instead of |.
         If B is constant and (B & M) == 0, fold into A & M.  */
 -      if (host_integerp (arg1, 1))
 +      if (TREE_CODE (arg1) == INTEGER_CST)
        {
 -        unsigned HOST_WIDE_INT cst1 = tree_low_cst (arg1, 1);
 -        if (~cst1 && (cst1 & (cst1 + 1)) == 0
 +        wide_int cst1 = arg1;
 +        if ((~cst1 != 0) && (cst1 & (cst1 + 1)) == 0
              && INTEGRAL_TYPE_P (TREE_TYPE (arg0))
              && (TREE_CODE (arg0) == PLUS_EXPR
                  || TREE_CODE (arg0) == MINUS_EXPR
            {
              tree pmop[2];
              int which = 0;
 -            unsigned HOST_WIDE_INT cst0;
 +            wide_int cst0;
  
              /* Now we know that arg0 is (C + D) or (C - D) or
                 -C and arg1 (M) is == (1LL << cst) - 1.
                  which = 1;
                }
  
 -            if (!host_integerp (TYPE_MAX_VALUE (TREE_TYPE (arg0)), 1)
 -                || (tree_low_cst (TYPE_MAX_VALUE (TREE_TYPE (arg0)), 1)
 -                    & cst1) != cst1)
 +            if ((wi::max_value (TREE_TYPE (arg0)) & cst1) != cst1)
                which = -1;
  
              for (; which >= 0; which--)
                    if (TREE_CODE (TREE_OPERAND (pmop[which], 1))
                        != INTEGER_CST)
                      break;
 -                  /* tree_low_cst not used, because we don't care about
 -                     the upper bits.  */
 -                  cst0 = TREE_INT_CST_LOW (TREE_OPERAND (pmop[which], 1));
 +                  cst0 = TREE_OPERAND (pmop[which], 1);
                    cst0 &= cst1;
                    if (TREE_CODE (pmop[which]) == BIT_AND_EXPR)
                      {
                       omitted (assumed 0).  */
                    if ((TREE_CODE (arg0) == PLUS_EXPR
                         || (TREE_CODE (arg0) == MINUS_EXPR && which == 0))
 -                      && (TREE_INT_CST_LOW (pmop[which]) & cst1) == 0)
 +                      && (cst1 & pmop[which]) == 0)
                      pmop[which] = NULL;
                    break;
                  default:
                }
            }
        }
 -
 +      
        t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
        if (t1 != NULL_TREE)
        return t1;
        {
          prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
  
 -        if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT
 -            && (~TREE_INT_CST_LOW (arg1)
 -                & (((HOST_WIDE_INT) 1 << prec) - 1)) == 0)
 +        wide_int mask = wide_int::from (arg1, prec, UNSIGNED);
 +        if (mask == -1)
            return
              fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
        }
        /* If arg0 is derived from the address of an object or function, we may
         be able to fold this expression using the object or function's
         alignment.  */
 -      if (POINTER_TYPE_P (TREE_TYPE (arg0)) && host_integerp (arg1, 1))
 +      if (POINTER_TYPE_P (TREE_TYPE (arg0)) && tree_fits_uhwi_p (arg1))
        {
          unsigned HOST_WIDE_INT modulus, residue;
 -        unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (arg1);
 +        unsigned HOST_WIDE_INT low = tree_to_uhwi (arg1);
  
          modulus = get_pointer_modulus_and_residue (arg0, &residue,
                                                     integer_onep (arg1));
         if the new mask might be further optimized.  */
        if ((TREE_CODE (arg0) == LSHIFT_EXPR
           || TREE_CODE (arg0) == RSHIFT_EXPR)
 -        && host_integerp (TREE_OPERAND (arg0, 1), 1)
 -        && host_integerp (arg1, TYPE_UNSIGNED (TREE_TYPE (arg1)))
 -        && tree_low_cst (TREE_OPERAND (arg0, 1), 1)
 +        && tree_fits_uhwi_p (TREE_OPERAND (arg0, 1))
 +        && tree_fits_hwi_p (arg1)
 +        && tree_to_uhwi (TREE_OPERAND (arg0, 1))
             < TYPE_PRECISION (TREE_TYPE (arg0))
          && TYPE_PRECISION (TREE_TYPE (arg0)) <= HOST_BITS_PER_WIDE_INT
 -        && tree_low_cst (TREE_OPERAND (arg0, 1), 1) > 0)
 +        && tree_to_uhwi (TREE_OPERAND (arg0, 1)) > 0)
        {
 -        unsigned int shiftc = tree_low_cst (TREE_OPERAND (arg0, 1), 1);
 +        unsigned int shiftc = tree_to_uhwi (TREE_OPERAND (arg0, 1));
          unsigned HOST_WIDE_INT mask
 -          = tree_low_cst (arg1, TYPE_UNSIGNED (TREE_TYPE (arg1)));
 +          = tree_to_hwi (arg1, TYPE_SIGN (TREE_TYPE (arg1)));
          unsigned HOST_WIDE_INT newmask, zerobits = 0;
          tree shift_type = TREE_TYPE (arg0);
  
          tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (arg1),
                                      arg1, TREE_OPERAND (arg0, 1));
          if (sum && integer_zerop (sum)) {
 -          unsigned long pow2;
 -
 -          if (TREE_INT_CST_LOW (arg1))
 -            pow2 = exact_log2 (TREE_INT_CST_LOW (arg1));
 -          else
 -            pow2 = exact_log2 (TREE_INT_CST_HIGH (arg1))
 -                    + HOST_BITS_PER_WIDE_INT;
 -
 +          tree pow2 = build_int_cst (integer_type_node,
 +                                     wi::exact_log2 (arg1));
            return fold_build2_loc (loc, RSHIFT_EXPR, type,
 -                        TREE_OPERAND (arg0, 0),
 -                        build_int_cst (integer_type_node, pow2));
 +                                  TREE_OPERAND (arg0, 0), pow2);
          }
        }
  
          if (integer_pow2p (sval) && tree_int_cst_sgn (sval) > 0)
            {
              tree sh_cnt = TREE_OPERAND (arg1, 1);
 -            unsigned long pow2;
 -
 -            if (TREE_INT_CST_LOW (sval))
 -              pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
 -            else
 -              pow2 = exact_log2 (TREE_INT_CST_HIGH (sval))
 -                     + HOST_BITS_PER_WIDE_INT;
 +            tree pow2 = build_int_cst (TREE_TYPE (sh_cnt),
 +                                       wi::exact_log2 (sval));
  
              if (strict_overflow_p)
                fold_overflow_warning (("assuming signed overflow does not "
                                       WARN_STRICT_OVERFLOW_MISC);
  
              sh_cnt = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (sh_cnt),
 -                                      sh_cnt,
 -                                      build_int_cst (TREE_TYPE (sh_cnt),
 -                                                     pow2));
 +                                      sh_cnt, pow2);
              return fold_build2_loc (loc, RSHIFT_EXPR, type,
 -                                fold_convert_loc (loc, type, arg0), sh_cnt);
 +                                    fold_convert_loc (loc, type, arg0), sh_cnt);
            }
        }
  
        /* X / -1 is -X.  */
        if (!TYPE_UNSIGNED (type)
          && TREE_CODE (arg1) == INTEGER_CST
 -        && TREE_INT_CST_LOW (arg1) == HOST_WIDE_INT_M1U
 -        && TREE_INT_CST_HIGH (arg1) == -1)
 +        && wi::eq_p (arg1, -1))
        return fold_convert_loc (loc, type, negate_expr (arg0));
  
        /* Convert -A / -B to A / B when the type is signed and overflow is
        /* X % -1 is zero.  */
        if (!TYPE_UNSIGNED (type)
          && TREE_CODE (arg1) == INTEGER_CST
 -        && TREE_INT_CST_LOW (arg1) == HOST_WIDE_INT_M1U
 -        && TREE_INT_CST_HIGH (arg1) == -1)
 +        && wi::eq_p (arg1, -1))
        return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
  
        /* X % -C is the same as X % C.  */
        if (code == TRUNC_MOD_EXPR
 -        && !TYPE_UNSIGNED (type)
 +        && TYPE_SIGN (type) == SIGNED
          && TREE_CODE (arg1) == INTEGER_CST
          && !TREE_OVERFLOW (arg1)
 -        && TREE_INT_CST_HIGH (arg1) < 0
 +        && wi::neg_p (arg1)
          && !TYPE_OVERFLOW_TRAPS (type)
          /* Avoid this transformation if C is INT_MIN, i.e. C == -C.  */
          && !sign_bit_p (arg1, arg1))
        prec = element_precision (type);
  
        /* Turn (a OP c1) OP c2 into a OP (c1+c2).  */
 -      if (TREE_CODE (op0) == code && host_integerp (arg1, true)
 -        && TREE_INT_CST_LOW (arg1) < prec
 -        && host_integerp (TREE_OPERAND (arg0, 1), true)
 -        && TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) < prec)
 +      if (TREE_CODE (op0) == code && tree_fits_uhwi_p (arg1)
 +        && tree_to_uhwi (arg1) < prec
 +        && tree_fits_uhwi_p (TREE_OPERAND (arg0, 1))
 +        && tree_to_uhwi (TREE_OPERAND (arg0, 1)) < prec)
        {
 -        unsigned int low = (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1))
 -                            + TREE_INT_CST_LOW (arg1));
 +        HOST_WIDE_INT low = (tree_to_shwi (TREE_OPERAND (arg0, 1))
 +                             + tree_to_shwi (arg1));
  
          /* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2
             being well defined.  */
        if (((code == LSHIFT_EXPR && TREE_CODE (arg0) == RSHIFT_EXPR)
             || (TYPE_UNSIGNED (type)
               && code == RSHIFT_EXPR && TREE_CODE (arg0) == LSHIFT_EXPR))
 -        && host_integerp (arg1, false)
 -        && TREE_INT_CST_LOW (arg1) < prec
 -        && host_integerp (TREE_OPERAND (arg0, 1), false)
 -        && TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) < prec)
 +        && tree_fits_shwi_p (arg1)
 +        && tree_to_shwi (arg1) < prec
 +        && tree_fits_shwi_p (TREE_OPERAND (arg0, 1))
 +        && tree_to_shwi (TREE_OPERAND (arg0, 1)) < prec)
        {
 -        HOST_WIDE_INT low0 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1));
 -        HOST_WIDE_INT low1 = TREE_INT_CST_LOW (arg1);
 +        HOST_WIDE_INT low0 = tree_to_shwi (TREE_OPERAND (arg0, 1));
 +        HOST_WIDE_INT low1 = tree_to_shwi (arg1);
          tree lshift;
          tree arg00;
  
                            fold_build2_loc (loc, code, type,
                                         TREE_OPERAND (arg0, 1), arg1));
  
 -      /* Two consecutive rotates adding up to the precision of the
 -       type can be ignored.  */
 +      /* Two consecutive rotates adding up to the some integer
 +       multiple of the precision of the type can be ignored.  */
        if (code == RROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (arg0) == RROTATE_EXPR
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
 -        && TREE_INT_CST_HIGH (arg1) == 0
 -        && TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)) == 0
 -        && ((TREE_INT_CST_LOW (arg1)
 -             + TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)))
 -            == prec))
 +        && wi::umod_trunc (wi::add (arg1, TREE_OPERAND (arg0, 1)),
 +                           prec) == 0)
        return TREE_OPERAND (arg0, 0);
  
        /* Fold (X & C2) << C1 into (X << C1) & (C2 << C1)
          && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0,
                                                                        1)),
                              arg1, 0)
 -        && (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 0)) & 1) == 1)
 +        && wi::bit_and (TREE_OPERAND (arg0, 0), 1) == 1)
        {
          return omit_two_operands_loc (loc, type,
                                    code == NE_EXPR
          prec = TYPE_PRECISION (itype);
  
          /* Check for a valid shift count.  */
 -        if (TREE_INT_CST_HIGH (arg001) == 0
 -            && TREE_INT_CST_LOW (arg001) < prec)
 +        if (wi::ltu_p (arg001, prec))
            {
              tree arg01 = TREE_OPERAND (arg0, 1);
              tree arg000 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
              unsigned HOST_WIDE_INT log2 = tree_log2 (arg01);
              /* If (C2 << C1) doesn't overflow, then ((X >> C1) & C2) != 0
                 can be rewritten as (X & (C2 << C1)) != 0.  */
 -            if ((log2 + TREE_INT_CST_LOW (arg001)) < prec)
 +            if ((log2 + tree_to_uhwi (arg001)) < prec)
                {
                  tem = fold_build2_loc (loc, LSHIFT_EXPR, itype, arg01, arg001);
                  tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, arg000, tem);
          tree arg00 = TREE_OPERAND (arg0, 0);
          tree arg01 = TREE_OPERAND (arg0, 1);
          tree itype = TREE_TYPE (arg00);
 -        if (TREE_INT_CST_HIGH (arg01) == 0
 -            && TREE_INT_CST_LOW (arg01)
 -               == (unsigned HOST_WIDE_INT) (TYPE_PRECISION (itype) - 1))
 +        if (wi::eq_p (arg01, TYPE_PRECISION (itype) - 1))
            {
              if (TYPE_UNSIGNED (itype))
                {
         the specified precision will have known values.  */
        {
        tree arg1_type = TREE_TYPE (arg1);
 -      unsigned int width = TYPE_PRECISION (arg1_type);
 +      unsigned int prec = TYPE_PRECISION (arg1_type);
  
        if (TREE_CODE (arg1) == INTEGER_CST
 -          && width <= HOST_BITS_PER_DOUBLE_INT
            && (INTEGRAL_TYPE_P (arg1_type) || POINTER_TYPE_P (arg1_type)))
          {
 -          HOST_WIDE_INT signed_max_hi;
 -          unsigned HOST_WIDE_INT signed_max_lo;
 -          unsigned HOST_WIDE_INT max_hi, max_lo, min_hi, min_lo;
 -
 -          if (width <= HOST_BITS_PER_WIDE_INT)
 -            {
 -              signed_max_lo = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
 -                              - 1;
 -              signed_max_hi = 0;
 -              max_hi = 0;
 -
 -              if (TYPE_UNSIGNED (arg1_type))
 -                {
 -                  max_lo = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
 -                  min_lo = 0;
 -                  min_hi = 0;
 -                }
 -              else
 -                {
 -                  max_lo = signed_max_lo;
 -                  min_lo = (HOST_WIDE_INT_M1U << (width - 1));
 -                  min_hi = -1;
 -                }
 -            }
 -          else
 -            {
 -              width -= HOST_BITS_PER_WIDE_INT;
 -              signed_max_lo = -1;
 -              signed_max_hi = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
 -                              - 1;
 -              max_lo = -1;
 -              min_lo = 0;
 -
 -              if (TYPE_UNSIGNED (arg1_type))
 -                {
 -                  max_hi = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
 -                  min_hi = 0;
 -                }
 -              else
 -                {
 -                  max_hi = signed_max_hi;
 -                  min_hi = (HOST_WIDE_INT_M1U << (width - 1));
 -                }
 -            }
 +          wide_int max = wi::max_value (arg1_type);
 +          wide_int signed_max = wi::max_value (prec, SIGNED);
 +          wide_int min = wi::min_value (arg1_type);
  
 -          if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) == max_hi
 -              && TREE_INT_CST_LOW (arg1) == max_lo)
 +          if (wi::eq_p (arg1, max))
              switch (code)
                {
                case GT_EXPR:
                default:
                  break;
                }
 -          else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
 -                   == max_hi
 -                   && TREE_INT_CST_LOW (arg1) == max_lo - 1)
 +          else if (wi::eq_p (arg1, max - 1))
              switch (code)
                {
                case GT_EXPR:
                default:
                  break;
                }
 -          else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
 -                   == min_hi
 -                   && TREE_INT_CST_LOW (arg1) == min_lo)
 +          else if (wi::eq_p (arg1, min))
              switch (code)
                {
                case LT_EXPR:
                default:
                  break;
                }
 -          else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
 -                   == min_hi
 -                   && TREE_INT_CST_LOW (arg1) == min_lo + 1)
 +          else if (wi::eq_p (arg1, min + 1))
              switch (code)
                {
                case GE_EXPR:
 -                arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node);
 +                arg1 = const_binop (MINUS_EXPR, arg1, 
 +                                    build_int_cst (TREE_TYPE (arg1), 1));
                  return fold_build2_loc (loc, NE_EXPR, type,
                                      fold_convert_loc (loc,
                                                        TREE_TYPE (arg1), arg0),
                                      arg1);
                case LT_EXPR:
 -                arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node);
 +                arg1 = const_binop (MINUS_EXPR, arg1, 
 +                                    build_int_cst (TREE_TYPE (arg1), 1));
                  return fold_build2_loc (loc, EQ_EXPR, type,
                                      fold_convert_loc (loc, TREE_TYPE (arg1),
                                                        arg0),
                  break;
                }
  
 -          else if (TREE_INT_CST_HIGH (arg1) == signed_max_hi
 -                   && TREE_INT_CST_LOW (arg1) == signed_max_lo
 +          else if (wi::eq_p (arg1, signed_max)
                     && TYPE_UNSIGNED (arg1_type)
 +                   /* KENNY QUESTIONS THE CHECKING OF THE BITSIZE
 +                      HERE.  HE FEELS THAT THE PRECISION SHOULD BE
 +                      CHECKED */
 +
                     /* We will flip the signedness of the comparison operator
                        associated with the mode of arg1, so the sign bit is
                        specified by this mode.  Check that arg1 is the signed
                        max associated with this sign bit.  */
 -                   && width == GET_MODE_BITSIZE (TYPE_MODE (arg1_type))
 +                   && prec == GET_MODE_BITSIZE (TYPE_MODE (arg1_type))
                     /* signed_type does not work on pointer types.  */
                     && INTEGRAL_TYPE_P (arg1_type))
              {
@@@ -14091,6 -14219,8 +14088,6 @@@ fold_ternary_loc (location_t loc, enum 
              && TYPE_PRECISION (TREE_TYPE (tem))
                 < TYPE_PRECISION (type))
            {
 -            unsigned HOST_WIDE_INT mask_lo;
 -            HOST_WIDE_INT mask_hi;
              int inner_width, outer_width;
              tree tem_type;
  
              if (outer_width > TYPE_PRECISION (type))
                outer_width = TYPE_PRECISION (type);
  
 -            if (outer_width > HOST_BITS_PER_WIDE_INT)
 -              {
 -                mask_hi = (HOST_WIDE_INT_M1U
 -                           >> (HOST_BITS_PER_DOUBLE_INT - outer_width));
 -                mask_lo = -1;
 -              }
 -            else
 -              {
 -                mask_hi = 0;
 -                mask_lo = (HOST_WIDE_INT_M1U
 -                           >> (HOST_BITS_PER_WIDE_INT - outer_width));
 -              }
 -            if (inner_width > HOST_BITS_PER_WIDE_INT)
 -              {
 -                mask_hi &= ~(HOST_WIDE_INT_M1U
 -                             >> (HOST_BITS_PER_WIDE_INT - inner_width));
 -                mask_lo = 0;
 -              }
 -            else
 -              mask_lo &= ~(HOST_WIDE_INT_M1U
 -                           >> (HOST_BITS_PER_WIDE_INT - inner_width));
 +            wide_int mask = wi::shifted_mask
 +              (inner_width, outer_width - inner_width, false, 
 +               TYPE_PRECISION (TREE_TYPE (arg1)));
  
 -            if ((TREE_INT_CST_HIGH (arg1) & mask_hi) == mask_hi
 -                && (TREE_INT_CST_LOW (arg1) & mask_lo) == mask_lo)
 +            wide_int common = mask & arg1;
 +            if (common == mask)
                {
                  tem_type = signed_type_for (TREE_TYPE (tem));
                  tem = fold_convert_loc (loc, tem_type, tem);
                }
 -            else if ((TREE_INT_CST_HIGH (arg1) & mask_hi) == 0
 -                     && (TREE_INT_CST_LOW (arg1) & mask_lo) == 0)
 +            else if (common == 0)
                {
                  tem_type = unsigned_type_for (TREE_TYPE (tem));
                  tem = fold_convert_loc (loc, tem_type, tem);
          tree tem = TREE_OPERAND (arg0, 0);
          STRIP_NOPS (tem);
          if (TREE_CODE (tem) == RSHIFT_EXPR
 -              && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
 +            && tree_fits_uhwi_p (TREE_OPERAND (tem, 1))
                && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
 -               TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
 +               tree_to_uhwi (TREE_OPERAND (tem, 1)))
            return fold_build2_loc (loc, BIT_AND_EXPR, type,
                                TREE_OPERAND (tem, 0), arg1);
        }
                  && TREE_TYPE (type) == TREE_TYPE (TREE_TYPE (arg0)))))
        {
          tree eltype = TREE_TYPE (TREE_TYPE (arg0));
 -        unsigned HOST_WIDE_INT width = tree_low_cst (TYPE_SIZE (eltype), 1);
 -        unsigned HOST_WIDE_INT n = tree_low_cst (arg1, 1);
 -        unsigned HOST_WIDE_INT idx = tree_low_cst (op2, 1);
 +        unsigned HOST_WIDE_INT width = tree_to_uhwi (TYPE_SIZE (eltype));
 +        unsigned HOST_WIDE_INT n = tree_to_uhwi (arg1);
 +        unsigned HOST_WIDE_INT idx = tree_to_uhwi (op2);
  
          if (n != 0
              && (idx % width) == 0
  
        /* A bit-field-ref that referenced the full argument can be stripped.  */
        if (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
 -        && TYPE_PRECISION (TREE_TYPE (arg0)) == tree_low_cst (arg1, 1)
 +        && TYPE_PRECISION (TREE_TYPE (arg0)) == tree_to_uhwi (arg1)
          && integer_zerop (op2))
        return fold_convert_loc (loc, type, arg0);
  
           fold (nearly) all BIT_FIELD_REFs.  */
        if (CONSTANT_CLASS_P (arg0)
          && can_native_interpret_type_p (type)
 -        && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (arg0)), 1)
 +        && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (arg0)))
          /* This limitation should not be necessary, we just need to
             round this up to mode size.  */
 -        && tree_low_cst (op1, 1) % BITS_PER_UNIT == 0
 +        && tree_to_uhwi (op1) % BITS_PER_UNIT == 0
          /* Need bit-shifting of the buffer to relax the following.  */
 -        && tree_low_cst (op2, 1) % BITS_PER_UNIT == 0)
 +        && tree_to_uhwi (op2) % BITS_PER_UNIT == 0)
        {
 -        unsigned HOST_WIDE_INT bitpos = tree_low_cst (op2, 1);
 -        unsigned HOST_WIDE_INT bitsize = tree_low_cst (op1, 1);
 +        unsigned HOST_WIDE_INT bitpos = tree_to_uhwi (op2);
 +        unsigned HOST_WIDE_INT bitsize = tree_to_uhwi (op1);
          unsigned HOST_WIDE_INT clen;
 -        clen = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (arg0)), 1);
 +        clen = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (arg0)));
          /* ???  We cannot tell native_encode_expr to start at
             some random byte only.  So limit us to a reasonable amount
             of work.  */
        {
          unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i, mask;
          unsigned char *sel = XALLOCAVEC (unsigned char, nelts);
 -        tree t;
          bool need_mask_canon = false;
          bool all_in_vec0 = true;
          bool all_in_vec1 = true;
              if (TREE_CODE (val) != INTEGER_CST)
                return NULL_TREE;
  
 -            sel[i] = TREE_INT_CST_LOW (val) & mask;
 -            if (TREE_INT_CST_HIGH (val)
 -                || ((unsigned HOST_WIDE_INT)
 -                    TREE_INT_CST_LOW (val) != sel[i]))
 -              need_mask_canon = true;
 +            /* Make sure that the perm value is in an acceptable
 +               range.  */
 +            wide_int t = val;
 +            if (wi::gtu_p (t, mask))
 +              {
 +                need_mask_canon = true;
 +                sel[i] = t.to_uhwi () & mask;
 +              }
 +            else
 +              sel[i] = t.to_uhwi ();
  
              if (sel[i] < nelts)
                all_in_vec1 = false;
              && (TREE_CODE (op1) == VECTOR_CST
                  || TREE_CODE (op1) == CONSTRUCTOR))
            {
 -            t = fold_vec_perm (type, op0, op1, sel);
 +            tree t = fold_vec_perm (type, op0, op1, sel);
              if (t != NULL_TREE)
                return t;
            }
@@@ -15202,7 -15347,9 +15199,7 @@@ multiple_of_p (tree type, const_tree to
          op1 = TREE_OPERAND (top, 1);
          /* const_binop may not detect overflow correctly,
             so check for it explicitly here.  */
 -        if (TYPE_PRECISION (TREE_TYPE (size_one_node))
 -            > TREE_INT_CST_LOW (op1)
 -            && TREE_INT_CST_HIGH (op1) == 0
 +        if (wi::gtu_p (TYPE_PRECISION (TREE_TYPE (size_one_node)), op1)
              && 0 != (t1 = fold_convert (type,
                                          const_binop (LSHIFT_EXPR,
                                                       size_one_node,
@@@ -15407,11 -15554,11 +15404,11 @@@ tree_binary_nonnegative_warnv_p (enum t
              && TREE_CODE (inner1) == INTEGER_TYPE && unsigned1)
            {
              unsigned int precision0 = (TREE_CODE (op0) == INTEGER_CST)
 -              ? tree_int_cst_min_precision (op0, /*unsignedp=*/true)
 +              ? tree_int_cst_min_precision (op0, UNSIGNED)
                : TYPE_PRECISION (inner0);
  
              unsigned int precision1 = (TREE_CODE (op1) == INTEGER_CST)
 -              ? tree_int_cst_min_precision (op1, /*unsignedp=*/true)
 +              ? tree_int_cst_min_precision (op1, UNSIGNED)
                : TYPE_PRECISION (inner1);
  
              return precision0 + precision1 < TYPE_PRECISION (type);
@@@ -15591,7 -15738,7 +15588,7 @@@ tree_call_nonnegative_warnv_p (tree typ
        /* True if the 1st argument is nonnegative or the second
           argument is an even integer.  */
        if (TREE_CODE (arg1) == INTEGER_CST
 -          && (TREE_INT_CST_LOW (arg1) & 1) == 0)
 +          && (tree_to_hwi (arg1) & 1) == 0)
          return true;
        return tree_expr_nonnegative_warnv_p (arg0,
                                              strict_overflow_p);
            if ((n & 1) == 0)
              {
                REAL_VALUE_TYPE cint;
 -              real_from_integer (&cint, VOIDmode, n,
 -                                 n < 0 ? -1 : 0, 0);
 +              real_from_integer (&cint, VOIDmode, n, SIGNED);
                if (real_identical (&c, &cint))
                  return true;
              }
@@@ -16186,7 -16334,7 +16183,7 @@@ fold_read_from_constant_string (tree ex
          && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (string)))) == 1))
        return build_int_cst_type (TREE_TYPE (exp),
                                   (TREE_STRING_POINTER (string)
 -                                  [TREE_INT_CST_LOW (index)]));
 +                                  [tree_to_uhwi (index)]));
      }
    return NULL;
  }
@@@ -16205,11 -16353,12 +16202,11 @@@ fold_negate_const (tree arg0, tree type
      {
      case INTEGER_CST:
        {
 -      double_int val = tree_to_double_int (arg0);
        bool overflow;
 -      val = val.neg_with_overflow (&overflow);
 -      t = force_fit_type_double (type, val, 1,
 -                                 (overflow | TREE_OVERFLOW (arg0))
 -                                 && !TYPE_UNSIGNED (type));
 +      wide_int val = wi::neg (arg0, &overflow);
 +      t = force_fit_type (type, val, 1,
 +                          (overflow | TREE_OVERFLOW (arg0))
 +                          && !TYPE_UNSIGNED (type));
        break;
        }
  
@@@ -16251,9 -16400,12 +16248,9 @@@ fold_abs_const (tree arg0, tree type
      {
      case INTEGER_CST:
        {
 -      double_int val = tree_to_double_int (arg0);
 -
          /* If the value is unsigned or non-negative, then the absolute value
           is the same as the ordinary value.  */
 -      if (TYPE_UNSIGNED (type)
 -          || !val.is_negative ())
 +      if (!wi::neg_p (arg0, TYPE_SIGN (type)))
          t = arg0;
  
        /* If the value is negative, then the absolute value is
        else
          {
            bool overflow;
 -          val = val.neg_with_overflow (&overflow);
 -          t = force_fit_type_double (type, val, -1,
 -                                     overflow | TREE_OVERFLOW (arg0));
 +          wide_int val = wi::neg (arg0, &overflow);
 +          t = force_fit_type (type, val, -1,
 +                              overflow | TREE_OVERFLOW (arg0));
          }
        }
        break;
  static tree
  fold_not_const (const_tree arg0, tree type)
  {
 -  double_int val;  
 -
    gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
  
 -  val = ~tree_to_double_int (arg0);
 -  return force_fit_type_double (type, val, 0, TREE_OVERFLOW (arg0));
 +  return force_fit_type (type, wi::bit_not (arg0), 0, TREE_OVERFLOW (arg0));
  }
  
  /* Given CODE, a relational operator, the target type, TYPE and two
@@@ -16433,6 -16588,8 +16430,6 @@@ fold_relational_const (enum tree_code c
      {
        if (code == EQ_EXPR)
        result = tree_int_cst_equal (op0, op1);
 -      else if (TYPE_UNSIGNED (TREE_TYPE (op0)))
 -      result = INT_CST_LT_UNSIGNED (op0, op1);
        else
        result = INT_CST_LT (op0, op1);
      }
@@@ -16552,10 -16709,9 +16549,10 @@@ fold_indirect_ref_1 (location_t loc, tr
          if (TREE_CODE (op00type) == VECTOR_TYPE
              && type == TREE_TYPE (op00type))
            {
 -            HOST_WIDE_INT offset = tree_low_cst (op01, 0);
 +            HOST_WIDE_INT offset = tree_to_shwi (op01);
              tree part_width = TYPE_SIZE (type);
 -            unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
 +            unsigned HOST_WIDE_INT part_widthi 
 +              = tree_to_shwi (part_width) / BITS_PER_UNIT;
              unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
              tree index = bitsize_int (indexi);
  
@@@ -16693,7 -16849,8 +16690,7 @@@ fold_ignored_result (tree t
        }
  }
  
 -/* Return the value of VALUE, rounded up to a multiple of DIVISOR.
 -   This can only be applied to objects of a sizetype.  */
 +/* Return the value of VALUE, rounded up to a multiple of DIVISOR. */
  
  tree
  round_up_loc (location_t loc, tree value, int divisor)
      {
        if (TREE_CODE (value) == INTEGER_CST)
        {
 -        double_int val = tree_to_double_int (value);
 +        wide_int val = value;
          bool overflow_p;
  
 -        if ((val.low & (divisor - 1)) == 0)
 +        if ((val & (divisor - 1)) == 0)
            return value;
  
          overflow_p = TREE_OVERFLOW (value);
 -        val.low &= ~(divisor - 1);
 -        val.low += divisor;
 -        if (val.low == 0)
 -          {
 -            val.high++;
 -            if (val.high == 0)
 -              overflow_p = true;
 -          }
 +        val &= ~(divisor - 1);
 +        val += divisor;
 +        if (val == 0)
 +          overflow_p = true;
  
 -        return force_fit_type_double (TREE_TYPE (value), val,
 -                                      -1, overflow_p);
 +        return force_fit_type (TREE_TYPE (value), val, -1, overflow_p);
        }
        else
        {
@@@ -16854,7 -17016,7 +16851,7 @@@ ptr_difference_const (tree e1, tree e2
        toffset2 = fold_convert (type, toffset2);
  
        tdiff = fold_build2 (MINUS_EXPR, type, toffset1, toffset2);
 -      if (!cst_and_fits_in_hwi (tdiff))
 +      if (!cst_fits_shwi_p (tdiff))
        return false;
  
        *diff = int_cst_value (tdiff);
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.  */
  
  
@@@ -110,6 -109,8 +110,8 @@@ gfc_element_size (gfc_expr *e
        return e->representation.length;
      case BT_DERIVED:
      case BT_CLASS:
+     case BT_VOID:
+     case BT_ASSUMED:
        {
        /* Determine type size without clobbering the typespec for ISO C
           binding types.  */
@@@ -152,7 -153,7 +154,7 @@@ gfc_target_expr_size (gfc_expr *e
  }
  
  
- /* The encode_* functions export a value into a buffer, and 
+ /* The encode_* functions export a value into a buffer, and
     return the number of bytes of the buffer that have been
     used.  */
  
@@@ -252,8 -253,8 +254,8 @@@ encode_derived (gfc_expr *source, unsig
        gcc_assert (cmp);
        if (!c->expr)
        continue;
 -      ptr = TREE_INT_CST_LOW(DECL_FIELD_OFFSET(cmp->backend_decl))
 -          + TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(cmp->backend_decl))/8;
 +      ptr = tree_to_hwi (DECL_FIELD_OFFSET(cmp->backend_decl))
 +          + tree_to_hwi (DECL_FIELD_BIT_OFFSET(cmp->backend_decl))/8;
  
        if (c->expr->expr_type == EXPR_NULL)
        {
@@@ -287,7 -288,7 +289,7 @@@ gfc_target_encode_expr (gfc_expr *sourc
              || source->expr_type == EXPR_STRUCTURE
              || source->expr_type == EXPR_SUBSTRING);
  
-   /* If we already have a target-memory representation, we use that rather 
+   /* If we already have a target-memory representation, we use that rather
       than recreating one.  */
    if (source->representation.string)
      {
@@@ -428,7 -429,7 +430,7 @@@ gfc_interpret_logical (int kind, unsign
  {
    tree t = native_interpret_expr (gfc_get_logical_type (kind), buffer,
                                  buffer_size);
 -  *logical = tree_to_double_int (t).is_zero () ? 0 : 1;
 +  *logical = wi::eq_p (t, 0) ? 0 : 1;
    return size_logical (kind);
  }
  
@@@ -497,7 -498,7 +499,7 @@@ gfc_interpret_derived (unsigned char *b
        /* Needed as gfc_typenode_for_spec as gfc_typenode_for_spec
         sets this to BT_INTEGER.  */
        result->ts.type = BT_DERIVED;
-       e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind, &result->where); 
+       e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind, &result->where);
        c = gfc_constructor_append_expr (&result->value.constructor, e, NULL);
        c->n.component = cmp;
        gfc_target_interpret_expr (buffer, buffer_size, e, true);
      {
        gfc_constructor *c;
        gfc_expr *e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind,
-                                          &result->where); 
+                                          &result->where);
        e->ts = cmp->ts;
  
        /* Copy shape, if needed.  */
         i.e. there are, e.g., no bit fields.  */
  
        gcc_assert (cmp->backend_decl);
 -      ptr = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (cmp->backend_decl));
 +      ptr = tree_to_hwi (DECL_FIELD_BIT_OFFSET (cmp->backend_decl));
        gcc_assert (ptr % 8 == 0);
 -      ptr = ptr/8 + TREE_INT_CST_LOW (DECL_FIELD_OFFSET (cmp->backend_decl));
 +      ptr = ptr/8 + tree_to_hwi (DECL_FIELD_OFFSET (cmp->backend_decl));
  
        gfc_target_interpret_expr (&buffer[ptr], buffer_size - ptr, e, true);
      }
-     
    return int_size_in_bytes (type);
  }
  
@@@ -568,31 -569,31 +570,31 @@@ gfc_target_interpret_expr (unsigned cha
    switch (result->ts.type)
      {
      case BT_INTEGER:
-       result->representation.length = 
+       result->representation.length =
          gfc_interpret_integer (result->ts.kind, buffer, buffer_size,
                               result->value.integer);
        break;
  
      case BT_REAL:
-       result->representation.length = 
+       result->representation.length =
          gfc_interpret_float (result->ts.kind, buffer, buffer_size,
                             result->value.real);
        break;
  
      case BT_COMPLEX:
-       result->representation.length = 
+       result->representation.length =
          gfc_interpret_complex (result->ts.kind, buffer, buffer_size,
                               result->value.complex);
        break;
  
      case BT_LOGICAL:
-       result->representation.length = 
+       result->representation.length =
          gfc_interpret_logical (result->ts.kind, buffer, buffer_size,
                               &result->value.logical);
        break;
  
      case BT_CHARACTER:
-       result->representation.length = 
+       result->representation.length =
          gfc_interpret_character (buffer, buffer_size, result);
        break;
  
        result->ts = CLASS_DATA (result)->ts;
        /* Fall through.  */
      case BT_DERIVED:
-       result->representation.length = 
+       result->representation.length =
          gfc_interpret_derived (buffer, buffer_size, result);
        gcc_assert (result->representation.length >= 0);
        break;
  }
  
  
- /* --------------------------------------------------------------- */ 
+ /* --------------------------------------------------------------- */
  /* Two functions used by trans-common.c to write overlapping
     equivalence initializers to a buffer.  This is added to the union
     and the original initializers freed.  */
@@@ -660,8 -661,8 +662,8 @@@ expr_to_char (gfc_expr *e, unsigned cha
          gcc_assert (cmp && cmp->backend_decl);
          if (!c->expr)
            continue;
 -          ptr = TREE_INT_CST_LOW(DECL_FIELD_OFFSET(cmp->backend_decl))
 -                      + TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(cmp->backend_decl))/8;
 +          ptr = tree_to_hwi (DECL_FIELD_OFFSET(cmp->backend_decl))
 +                      + tree_to_hwi (DECL_FIELD_BIT_OFFSET(cmp->backend_decl))/8;
          expr_to_char (c->expr, &data[ptr], &chk[ptr], len);
        }
        return len;
@@@ -792,7 -793,7 +794,7 @@@ gfc_convert_boz (gfc_expr *expr, gfc_ty
        gfc_interpret_complex (ts->kind, buffer, buffer_size,
                             expr->value.complex);
      }
-   expr->is_boz = 0;  
+   expr->is_boz = 0;
    expr->ts.type = ts->type;
    expr->ts.kind = ts->kind;
  
index 48ab65450711b27af3f18d768ef251e3b4d4e2f4,fa84d5dab8154d1b5083bebb1ade09b26e1aa107..03ceea7417baa3c152e5272c09841db28b50f63f
@@@ -861,6 -861,8 +861,6 @@@ gfc_init_types (void
    int index;
    tree type;
    unsigned n;
 -  unsigned HOST_WIDE_INT hi;
 -  unsigned HOST_WIDE_INT lo;
  
    /* Create and name the types.  */
  #define PUSH_TYPE(name, node) \
       descriptor.  */
  
    n = TYPE_PRECISION (gfc_array_index_type) - GFC_DTYPE_SIZE_SHIFT;
 -  lo = ~ (unsigned HOST_WIDE_INT) 0;
 -  if (n > HOST_BITS_PER_WIDE_INT)
 -    hi = lo >> (2*HOST_BITS_PER_WIDE_INT - n);
 -  else
 -    hi = 0, lo >>= HOST_BITS_PER_WIDE_INT - n;
 -  gfc_max_array_element_size
 -    = build_int_cst_wide (long_unsigned_type_node, lo, hi);
 +  gfc_max_array_element_size 
 +    = wide_int_to_tree (long_unsigned_type_node, 
 +                      wi::mask (n, UNSIGNED,
 +                                TYPE_PRECISION (long_unsigned_type_node)));
  
    boolean_type_node = gfc_get_logical_type (gfc_default_logical_kind);
    boolean_true_node = build_int_cst (boolean_type_node, 1);
@@@ -1094,6 -1099,12 +1094,12 @@@ gfc_typenode_for_spec (gfc_typespec * s
        basetype = gfc_get_character_type (spec->kind, spec->u.cl);
        break;
  
+     case BT_HOLLERITH:
+       /* Since this cannot be used, return a length one character.  */
+       basetype = gfc_get_character_type_len (gfc_default_character_kind,
+                                            gfc_index_one_node);
+       break;
      case BT_DERIVED:
      case BT_CLASS:
        basetype = gfc_get_derived_type (spec->u.derived);
@@@ -1444,7 -1455,7 +1450,7 @@@ gfc_get_dtype (tree type
        if (tree_int_cst_lt (gfc_max_array_element_size, size))
        gfc_fatal_error ("Array element size too big at %C");
  
 -      i += TREE_INT_CST_LOW (size) << GFC_DTYPE_SIZE_SHIFT;
 +      i += tree_to_hwi (size) << GFC_DTYPE_SIZE_SHIFT;
      }
    dtype = build_int_cst (gfc_array_index_type, i);
  
@@@ -1882,7 -1893,7 +1888,7 @@@ gfc_get_array_type_bounds (tree etype, 
    if (stride)
      rtype = build_range_type (gfc_array_index_type, gfc_index_zero_node,
                              int_const_binop (MINUS_EXPR, stride,
 -                                             integer_one_node));
 +                                             build_int_cst (TREE_TYPE (stride), 1)));
    else
      rtype = gfc_array_range_type;
    arraytype = build_array_type (etype, rtype);
diff --combined gcc/function.c
index ae56aedcdae2fc1462bc27831a2fc19726fc631f,21ab691c586a43d86f629d9c71e4f5ba3d3c1611..aace4361e9be4370c2b1517ab8e4988efe298619
@@@ -3825,8 -3825,8 +3825,8 @@@ locate_and_pad_parm (enum machine_mode 
    {
      tree s2 = sizetree;
      if (where_pad != none
 -      && (!host_integerp (sizetree, 1)
 -          || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % round_boundary))
 +      && (!tree_fits_uhwi_p (sizetree)
 +          || (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
        s2 = round_up (s2, round_boundary / BITS_PER_UNIT);
      SUB_PARM_SIZE (locate->slot_offset, s2);
    }
  
  #ifdef PUSH_ROUNDING
    if (passed_mode != BLKmode)
 -    sizetree = size_int (PUSH_ROUNDING (TREE_INT_CST_LOW (sizetree)));
 +    sizetree = size_int (PUSH_ROUNDING (tree_to_hwi (sizetree)));
  #endif
  
    /* Pad_below needs the pre-rounded size to know how much to pad below
      pad_below (&locate->offset, passed_mode, sizetree);
  
    if (where_pad != none
 -      && (!host_integerp (sizetree, 1)
 -        || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % round_boundary))
 +      && (!tree_fits_uhwi_p (sizetree)
 +        || (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
      sizetree = round_up (sizetree, round_boundary / BITS_PER_UNIT);
  
    ADD_PARM_SIZE (locate->size, sizetree);
@@@ -3970,7 -3970,7 +3970,7 @@@ pad_below (struct args_size *offset_ptr
    else
      {
        if (TREE_CODE (sizetree) != INTEGER_CST
 -        || (TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)
 +        || (tree_to_hwi (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)
        {
          /* Round the size up to multiple of PARM_BOUNDARY bits.  */
          tree s2 = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
  reorder_blocks (void)
  {
    tree block = DECL_INITIAL (current_function_decl);
-   vec<tree> block_stack;
  
    if (block == NULL_TREE)
      return;
  
-   block_stack.create (10);
+   stack_vec<tree, 10> block_stack;
  
    /* Reset the TREE_ASM_WRITTEN bit for all blocks.  */
    clear_block_marks (block);
    /* Recreate the block tree from the note nesting.  */
    reorder_blocks_1 (get_insns (), block, &block_stack);
    BLOCK_SUBBLOCKS (block) = blocks_nreverse_all (BLOCK_SUBBLOCKS (block));
-   block_stack.release ();
  }
  
  /* Helper function for reorder_blocks.  Reset TREE_ASM_WRITTEN.  */
diff --combined gcc/gcse.c
index 0d02d0a0312cdfd33ee66bcb5a6c749f0b9c2654,571e8788c83db469d06876e2b9c1e2ea94e9ea36..a00bbfab88175befc8ab7091f8ed1938a9f1aafb
@@@ -1997,13 -1997,6 +1997,13 @@@ prune_insertions_deletions (int n_elems
        bitmap_clear_bit (pre_delete_map[i], j);
      }
  
 +  if (dump_file)
 +    {
 +      dump_bitmap_vector (dump_file, "pre_insert_map", "", pre_insert_map, n_edges);
 +      dump_bitmap_vector (dump_file, "pre_delete_map", "", pre_delete_map,
 +                         last_basic_block);
 +    }
 +
    sbitmap_free (prune_exprs);
    free (insertions);
    free (deletions);
@@@ -2542,7 -2535,7 +2542,7 @@@ gcse_emit_move_after (rtx dest, rtx src
  /* Delete redundant computations.
     Deletion is done by changing the insn to copy the `reaching_reg' of
     the expression into the result of the SET.  It is left to later passes
-    (cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it.
+    to propagate the copy or eliminate it.
  
     Return nonzero if a change is made.  */
  
diff --combined gcc/genemit.c
index 223999ac1659003278aea940a24c2315dc219492,724a114da4461dff347796a102498cfd24679613..45d3936ddba02f8021083b70fc3216e557058288
@@@ -204,7 -204,6 +204,7 @@@ gen_exp (rtx x, enum rtx_code subroutin
  
      case CONST_DOUBLE:
      case CONST_FIXED:
 +    case CONST_WIDE_INT:
        /* These shouldn't be written in MD files.  Instead, the appropriate
         routines in varasm.c should be called.  */
        gcc_unreachable ();
@@@ -791,6 -790,7 +791,7 @@@ from the machine description file `md'
    printf ("#include \"system.h\"\n");
    printf ("#include \"coretypes.h\"\n");
    printf ("#include \"tm.h\"\n");
+   printf ("#include \"tree.h\"\n");
    printf ("#include \"rtl.h\"\n");
    printf ("#include \"tm_p.h\"\n");
    printf ("#include \"function.h\"\n");
diff --combined gcc/gengtype-parse.c
index 244ddcc85a1cbc5872fd84b7ff61348fbaed9ed4,f480503f8f1b3644218261a63ed7635e28fdccb5..9fb554c628e4d7f601bbc16f73c570599f3ebe18
@@@ -165,6 -165,21 +165,21 @@@ require (int t
    return v;
  }
  
+ /* As per require, but do not advance.  */
+ static const char *
+ require_without_advance (int t)
+ {
+   int u = token ();
+   const char *v = T.value;
+   if (u != t)
+     {
+       parse_error ("expected %s, have %s",
+                  print_token (t, 0), print_token (u, v));
+       return 0;
+     }
+   return v;
+ }
  /* If the next token does not have one of the codes T1 or T2, report a
     parse error; otherwise return the token's value.  */
  static const char *
@@@ -182,23 -197,6 +197,23 @@@ require2 (int t1, int t2
    return v;
  }
  
 +/* If the next token does not have one of the codes T1, T2 or T3, report a
 +   parse error; otherwise return the token's value.  */
 +static const char *
 +require3 (int t1, int t2, int t3)
 +{
 +  int u = token ();
 +  const char *v = advance ();
 +  if (u != t1 && u != t2 && u != t3)
 +    {
 +      parse_error ("expected %s, %s or %s, have %s",
 +                 print_token (t1, 0), print_token (t2, 0),
 +                 print_token (t3, 0), print_token (u, v));
 +      return 0;
 +    }
 +  return v;
 +}
 +
  /* Near-terminals.  */
  
  /* C-style string constant concatenation: STRING+
@@@ -245,45 -243,18 +260,45 @@@ require_template_declaration (const cha
    str = concat (tmpl_name, "<", (char *) 0);
  
    /* Read the comma-separated list of identifiers.  */
 -  while (token () != '>')
 +  int depth = 1;
 +  while (depth > 0)
      {
 -      const char *id = require2 (ID, ',');
 +      if (token () == ENUM)
 +      {
 +        advance ();
 +        str = concat (str, "enum ", (char *) 0);
 +        continue;
 +      }
 +      if (token () == NUM)
 +      {
 +        str = concat (str, advance (), (char *) 0);
 +        continue;
 +      }
 +      if (token () == ':')
 +      {
 +        advance ();
 +        str = concat (str, ":", (char *) 0);
 +        continue;
 +      }
 +      if (token () == '<')
 +      {
 +        advance ();
 +        str = concat (str, "<", (char *) 0);
 +        depth += 1;
 +        continue;
 +      }
 +      if (token () == '>')
 +      {
 +        advance ();
 +        str = concat (str, ">", (char *) 0);
 +        depth -= 1;
 +        continue;
 +      }
 +      const char *id = require3 (SCALAR, ID, ',');
        if (id == NULL)
        id = ",";
        str = concat (str, id, (char *) 0);
      }
 -
 -  /* Recognize the closing '>'.  */
 -  require ('>');
 -  str = concat (str, ">", (char *) 0);
 -
    return str;
  }
  
@@@ -822,7 -793,7 +837,7 @@@ struct_field_seq (void
  
  /* Return true if OPTS contain the option named STR.  */
  
static bool
+ bool
  opts_have (options_p opts, const char *str)
  {
    for (options_p opt = opts; opt; opt = opt->next)
@@@ -873,6 -844,7 +888,7 @@@ type (options_p *optsp, bool nested
      case STRUCT:
      case UNION:
        {
+       type_p base_class = NULL;
        options_p opts = 0;
        /* GTY annotations follow attribute syntax
           GTY_BEFORE_ID is for union/struct declarations
            opts = gtymarker_opt ();
          }
  
+       bool is_user_gty = opts_have (opts, "user");
        if (token () == ':')
          {
-           /* Skip over C++ inheritance specification.  */
-           while (token () != '{')
-             advance ();
+           if (is_gty && !is_user_gty)
+             {
+               /* For GTY-marked types that are not "user", parse some C++
+                  inheritance specifications.
+                  We require single-inheritance from a non-template type.  */
+               advance ();
+               const char *basename = require (ID);
+               /* This may be either an access specifier, or the base name.  */
+               if (0 == strcmp (basename, "public")
+                   || 0 == strcmp (basename, "protected")
+                   || 0 == strcmp (basename, "private"))
+                 basename = require (ID);
+               base_class = find_structure (basename, TYPE_STRUCT);
+               if (!base_class)
+                 parse_error ("unrecognized base class: %s", basename);
+               require_without_advance ('{');
+             }
+           else
+             {
+               /* For types lacking GTY-markings, skip over C++ inheritance
+                  specification (and thus avoid having to parse e.g. template
+                  types).  */
+               while (token () != '{')
+                 advance ();
+             }
          }
  
        if (is_gty)
          {
-           bool is_user_gty = opts_have (opts, "user");
            if (token () == '{')
              {
                pair_p fields;
                    return create_user_defined_type (s, &lexer_line);
                  }
  
-               return new_structure (s, kind, &lexer_line, fields, opts);
+               return new_structure (s, kind, &lexer_line, fields, opts,
+                                     base_class);
              }
          }
        else if (token () == '{')
diff --combined gcc/gengtype-state.c
index 0b5cf8f08662ff36c2443faf486a2e189d2d9369,fda473a2dbe5e5774806a18598c0f516516b8cad..ed61375283a8935591a627c685cdc698da5a0d16
@@@ -30,6 -30,7 +30,6 @@@
  #endif
  #include "system.h"
  #include "errors.h"   /* For fatal.  */
 -#include "double-int.h"
  #include "hashtab.h"
  #include "version.h"  /* For version_string & pkgversion_string.  */
  #include "obstack.h"
@@@ -956,6 -957,7 +956,7 @@@ state_writer::write_state_struct_type (
  {
    write_state_struct_union_type (current, "struct");
    write_state_type (current->u.s.lang_struct);
+   write_state_type (current->u.s.base_class);
  }
  
  /* Write a GTY user-defined struct type.  */
@@@ -1612,6 -1614,9 +1613,9 @@@ read_state_struct_type (type_p type
        read_state_options (&(type->u.s.opt));
        read_state_lang_bitmap (&(type->u.s.bitmap));
        read_state_type (&(type->u.s.lang_struct));
+       read_state_type (&(type->u.s.base_class));
+       if (type->u.s.base_class)
+       add_subclass (type->u.s.base_class, type);
      }
    else
      {
diff --combined gcc/gengtype.c
index e2d9dd4f9476fc214bf07dd3b3defafe22e15fa9,f35952e5a55583bc8587dc84804ea48f172f6458..c82536df206bace8a1fc3e9578880b3b10d1617a
@@@ -25,6 -25,7 +25,6 @@@
  #include "system.h"
  #include "errors.h"           /* for fatal */
  #include "getopt.h"
 -#include "double-int.h"
  #include "version.h"          /* for version_string & pkgversion_string.  */
  #include "hashtab.h"
  #include "xregex.h"
@@@ -136,6 -137,16 +136,16 @@@ xasprintf (const char *format, ...
    return result;
  }
  \f
+ /* Locate the ultimate base class of struct S.  */
+ static const_type_p
+ get_ultimate_base_class (const_type_p s)
+ {
+   while (s->u.s.base_class)
+     s = s->u.s.base_class;
+   return s;
+ }
\f
  /* Input file handling. */
  
  /* Table of all input files.  */
@@@ -524,7 -535,7 +534,7 @@@ do_typedef (const char *s, type_p t, st
    for (p = typedefs; p != NULL; p = p->next)
      if (strcmp (p->name, s) == 0)
        {
 -      if (p->type != t)
 +      if (p->type != t && strcmp (s, "result_type") != 0)
          {
            error_at_line (pos, "type `%s' previously defined", s);
            error_at_line (&p->line, "previously defined here");
@@@ -666,6 -677,16 +676,16 @@@ resolve_typedef (const char *s, struct 
    return p;
  }
  
+ /* Add SUBCLASS to head of linked list of BASE's subclasses.  */
+ void add_subclass (type_p base, type_p subclass)
+ {
+   gcc_assert (union_or_struct_p (base));
+   gcc_assert (union_or_struct_p (subclass));
+   subclass->u.s.next_sibling_class = base->u.s.first_subclass;
+   base->u.s.first_subclass = subclass;
+ }
  
  /* Create and return a new structure with tag NAME at POS with fields
     FIELDS and options O.  The KIND of structure must be one of
  
  type_p
  new_structure (const char *name, enum typekind kind, struct fileloc *pos,
-              pair_p fields, options_p o)
+              pair_p fields, options_p o, type_p base_class)
  {
    type_p si;
    type_p s = NULL;
    s->u.s.bitmap = bitmap;
    if (s->u.s.lang_struct)
      s->u.s.lang_struct->u.s.bitmap |= bitmap;
+   s->u.s.base_class = base_class;
+   if (base_class)
+     add_subclass (base_class, s);
  
    return s;
  }
@@@ -975,7 -999,7 +998,7 @@@ create_optional_field_ (pair_p next, ty
      create_string_option (union_fields->opt, "tag", "1");
    union_type = 
      new_structure (xasprintf ("%s_%d", "fake_union", id++), TYPE_UNION,
-                    &lexer_line, union_fields, NULL);
+                    &lexer_line, union_fields, NULL, NULL);
  
    /* Create the field and give it the new fake union type.  Add a "desc"
       tag that specifies the condition under which the field is valid.  */
@@@ -1166,7 -1190,7 +1189,7 @@@ adjust_field_rtx_def (type_p t, options
            create_string_option (nodot, "tag", note_insn_name[c]);
        }
      note_union_tp = new_structure ("rtx_def_note_subunion", TYPE_UNION,
-                                  &lexer_line, note_flds, NULL);
+                                  &lexer_line, note_flds, NULL, NULL);
    }
    /* Create a type to represent the various forms of SYMBOL_REF_DATA.  */
    {
      sym_flds = create_field (sym_flds, constant_tp, "rt_constant");
      sym_flds->opt = create_string_option (nodot, "tag", "1");
      symbol_union_tp = new_structure ("rtx_def_symbol_subunion", TYPE_UNION,
-                                    &lexer_line, sym_flds, NULL);
+                                    &lexer_line, sym_flds, NULL, NULL);
    }
    for (i = 0; i < NUM_RTX_CODE; i++)
      {
  
        sname = xasprintf ("rtx_def_%s", rtx_name[i]);
        substruct = new_structure (sname, TYPE_STRUCT, &lexer_line, subfields,
-                                NULL);
+                                NULL, NULL);
  
        ftag = xstrdup (rtx_name[i]);
        for (nmindex = 0; nmindex < strlen (ftag); nmindex++)
        flds->opt = create_string_option (nodot, "tag", ftag);
      }
    return new_structure ("rtx_def_subunion", TYPE_UNION, &lexer_line, flds,
-                       nodot);
+                       nodot, NULL);
  }
  
  /* Handle `special("tree_exp")'.  This is a special case for
@@@ -1357,7 -1381,7 +1380,7 @@@ adjust_field_tree_exp (type_p t, option
    flds->opt = create_string_option (flds->opt, "default", "");
  
    return new_structure ("tree_exp_subunion", TYPE_UNION, &lexer_line, flds,
-                       nodot);
+                       nodot, NULL);
  }
  
  /* Perform any special processing on a type T, about to become the type
@@@ -1530,7 -1554,17 +1553,17 @@@ set_gc_used_type (type_p t, enum gc_use
        process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy,
                            &dummy2);
  
-       for (f = t->u.s.fields; f; f = f->next)
+       if (t->u.s.base_class)
+         set_gc_used_type (t->u.s.base_class, level, param,
+                           allow_undefined_types);
+       /* Anything pointing to a base class might actually be pointing
+          to a subclass.  */
+       for (type_p subclass = t->u.s.first_subclass; subclass;
+            subclass = subclass->u.s.next_sibling_class)
+         set_gc_used_type (subclass, level, param,
+                           allow_undefined_types);
+       FOR_ALL_INHERITED_FIELDS(t, f)
          {
            int maybe_undef = 0;
            int pass_param = 0;
@@@ -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
      };
@@@ -2338,6 -2376,8 +2375,8 @@@ is_file_equal (outf_p of
          break;
        }
      }
+   if (equal && EOF != fgetc (newfile))
+     equal = false;
    fclose (newfile);
    return equal;
  }
@@@ -2539,6 -2579,10 +2578,10 @@@ output_mangled_typename (outf_p of, con
        case TYPE_LANG_STRUCT:
        case TYPE_USER_STRUCT:
        {
+         /* For references to classes within an inheritance hierarchy,
+            only ever reference the ultimate base class, since only
+            it will have gt_ functions.  */
+         t = get_ultimate_base_class (t);
          const char *id_for_tag = filter_type_name (t->u.s.tag);
          oprintf (of, "%lu%s", (unsigned long) strlen (id_for_tag),
                   id_for_tag);
@@@ -2601,6 -2645,42 +2644,42 @@@ output_escaped_param (struct walk_type_
        }
  }
  
+ const char *
+ get_string_option (options_p opt, const char *key)
+ {
+   for (; opt; opt = opt->next)
+     if (strcmp (opt->name, key) == 0)
+       return opt->info.string;
+   return NULL;
+ }
+ static void
+ walk_subclasses (type_p base, struct walk_type_data *d)
+ {
+   for (type_p sub = base->u.s.first_subclass; sub != NULL;
+        sub = sub->u.s.next_sibling_class)
+     {
+       const char *type_tag = get_string_option (sub->u.s.opt, "tag");
+       if (type_tag)
+       {
+         oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
+         d->indent += 2;
+         oprintf (d->of, "%*s{\n", d->indent, "");
+         d->indent += 2;
+         oprintf (d->of, "%*s%s *sub = static_cast <%s *> (x);\n",
+                  d->indent, "", sub->u.s.tag, sub->u.s.tag);
+         const char *old_val = d->val;
+         d->val = "(*sub)";
+         walk_type (sub, d);
+         d->val = old_val;
+         d->indent -= 2;
+         oprintf (d->of, "%*s}\n", d->indent, "");
+         oprintf (d->of, "%*sbreak;\n", d->indent, "");
+         d->indent -= 2;
+       }
+       walk_subclasses (sub, d);
+     }
+ }
  
  /* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
     which is of type T.  Write code to D->OF to constrain execution (at
@@@ -2618,6 -2698,7 +2697,7 @@@ walk_type (type_p t, struct walk_type_d
  {
    const char *length = NULL;
    const char *desc = NULL;
+   const char *type_tag = NULL;
    int maybe_undef_p = 0;
    int use_param_num = -1;
    int use_params_p = 0;
      else if (strcmp (oo->name, "dot") == 0)
        ;
      else if (strcmp (oo->name, "tag") == 0)
-       ;
+       type_tag = oo->info.string;
      else if (strcmp (oo->name, "special") == 0)
        ;
      else if (strcmp (oo->name, "skip") == 0)
            d->indent += 2;
            oprintf (d->of, "%*s{\n", d->indent, "");
          }
+       else if (desc)
+         {
+           /* We have a "desc" option on a struct, signifying the
+              base class within a GC-managed inheritance hierarchy.
+              The current code specialcases the base class, then walks
+              into subclasses, recursing into this routine to handle them.
+              This organization requires the base class to have a case in
+              the switch statement, and hence a tag value is mandatory
+              for the base class.   This restriction could be removed, but
+              it would require some restructing of this code.  */
+           if (!type_tag)
+             {
+               error_at_line (d->line,
+                              "missing `tag' option for type `%s'",
+                              t->u.s.tag);
+             }
+           oprintf (d->of, "%*sswitch (", d->indent, "");
+           output_escaped_param (d, desc, "desc");
+           oprintf (d->of, ")\n");
+           d->indent += 2;
+           oprintf (d->of, "%*s{\n", d->indent, "");
+           oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
+           d->indent += 2;
+         }
  
-       for (f = t->u.s.fields; f; f = f->next)
+       FOR_ALL_INHERITED_FIELDS (t, f)
          {
            options_p oo;
            int skip_p = 0;
          }
        endcounter = d->counter;
  
-       for (f = t->u.s.fields; f; f = f->next)
+       FOR_ALL_INHERITED_FIELDS (t, f)
          {
            options_p oo;
            const char *dot = ".";
            oprintf (d->of, "%*sdefault:\n", d->indent, "");
            oprintf (d->of, "%*s  break;\n", d->indent, "");
          }
+       if (desc && !union_p)
+         {
+               oprintf (d->of, "%*sbreak;\n", d->indent, "");
+               d->indent -= 2;
+           }
        if (union_p)
          {
            oprintf (d->of, "%*s}\n", d->indent, "");
            d->indent -= 2;
          }
+       else if (desc)
+         {
+           /* Add cases to handle subclasses.  */
+           walk_subclasses (t, d);
+           /* Ensure that if someone forgets a "tag" option that we don't
+              silent fail to traverse that subclass's fields.  */
+           if (!seen_default_p)
+             {
+               oprintf (d->of, "%*s/* Unrecognized tag value.  */\n",
+                        d->indent, "");
+               oprintf (d->of, "%*sdefault: gcc_unreachable (); \n",
+                        d->indent, "");
+             }
+           /* End of the switch statement */
+           oprintf (d->of, "%*s}\n", d->indent, "");
+           d->indent -= 2;
+         }
        if (any_length_seen)
          {
            d->indent -= 2;
@@@ -3456,6 -3586,24 +3585,24 @@@ write_func_for_structure (type_p orig_s
    options_p opt;
    struct walk_type_data d;
  
+   if (s->u.s.base_class)
+     {
+       /* Verify that the base class has a "desc", since otherwise
+        the traversal hooks there won't attempt to visit fields of
+        subclasses such as this one.  */
+       const_type_p ubc = get_ultimate_base_class (s);
+       if ((!opts_have (ubc->u.s.opt, "user")
+          && !opts_have (ubc->u.s.opt, "desc")))
+       error_at_line (&s->u.s.line,
+                      ("'%s' is a subclass of non-GTY(user) GTY class '%s'"
+                       ", but '%s' lacks a discriminator 'desc' option"),
+                      s->u.s.tag, ubc->u.s.tag, ubc->u.s.tag);
+       /* Don't write fns for subclasses, only for the ultimate base class
+        within an inheritance hierarchy.  */
+       return;
+     }
    memset (&d, 0, sizeof (d));
    d.of = get_output_file_for_structure (s, param);
    for (opt = s->u.s.opt; opt; opt = opt->next)
@@@ -3632,7 -3780,10 +3779,10 @@@ write_types (outf_p output_header, type
       emitted afterwards.  This is needed in plugin mode.  */
    oprintf (output_header, "/* Macros and declarations.  */\n");
    for (s = structures; s; s = s->next)
-     if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
+     /* Do not emit handlers for derived classes; we only ever deal with
+        the ultimate base class within an inheritance hierarchy.  */
+     if ((s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
+         && !s->u.s.base_class)
        {
        options_p opt;
  
@@@ -3937,6 -4088,11 +4087,11 @@@ write_local_func_for_structure (const_t
  {
    struct walk_type_data d;
  
+   /* Don't write fns for subclasses, only for the ultimate base class
+      within an inheritance hierarchy.  */
+   if (s->u.s.base_class)
+     return;
    memset (&d, 0, sizeof (d));
    d.of = get_output_file_for_structure (s, param);
    d.process_field = write_types_local_process_field;
@@@ -4081,7 -4237,9 +4236,9 @@@ write_local (outf_p output_header, type
           || ((s)->gc_used == GC_MAYBE_POINTED_TO                      \
               && s->u.s.line.file != NULL)                             \
           || ((s)->gc_used == GC_USED                                  \
-              && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))))))
+              && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))) \
+          || (s->u.s.base_class && opts_have (s->u.s.opt, "tag")))))
  
  
  /* Might T contain any non-pointer elements?  */
@@@ -4356,7 -4514,7 +4513,7 @@@ write_root (outf_p f, pair_p v, type_p 
  
      case TYPE_POINTER:
        {
-       type_p tp;
+       const_type_p tp;
  
        if (!start_root_entry (f, v, name, line))
          return;
  
        if (!has_length && union_or_struct_p (tp))
          {
+           tp = get_ultimate_base_class (tp);
            const char *id_for_tag = filter_type_name (tp->u.s.tag);
            oprintf (f, "    &gt_ggc_mx_%s,\n", id_for_tag);
            if (emit_pch)
@@@ -5474,9 -5633,6 +5632,9 @@@ main (int argc, char **argv
        POS_HERE (do_scalar_typedef ("REAL_VALUE_TYPE", &pos));
        POS_HERE (do_scalar_typedef ("FIXED_VALUE_TYPE", &pos));
        POS_HERE (do_scalar_typedef ("double_int", &pos));
 +      POS_HERE (do_scalar_typedef ("double_int_storage", &pos));
 +      POS_HERE (do_scalar_typedef ("offset_int", &pos));
 +      POS_HERE (do_scalar_typedef ("widest_int", &pos));
        POS_HERE (do_scalar_typedef ("uint64_t", &pos));
        POS_HERE (do_scalar_typedef ("uint8", &pos));
        POS_HERE (do_scalar_typedef ("uintptr_t", &pos));
diff --combined gcc/genmodes.c
index 8122a3ff924e0a992bfce93a1a6a220581fb71df,12a98f301628bd835cdbcc044c78bd598413d8b6..6f0fba85ec4170c026f8fa91e8fc7e360049b912
@@@ -333,6 -333,7 +333,7 @@@ complete_mode (struct mode_data *m
        break;
  
      case MODE_INT:
+     case MODE_POINTER_BOUNDS:
      case MODE_FLOAT:
      case MODE_DECIMAL_FLOAT:
      case MODE_FRACT:
@@@ -534,6 -535,19 +535,19 @@@ make_special_mode (enum mode_class cl, 
    new_mode (cl, name, file, line);
  }
  
+ #define POINTER_BOUNDS_MODE(N, Y) \
+   make_pointer_bounds_mode (#N, Y, __FILE__, __LINE__)
+ static void ATTRIBUTE_UNUSED
+ make_pointer_bounds_mode (const char *name,
+                         unsigned int bytesize,
+                         const char *file, unsigned int line)
+ {
+   struct mode_data *m = new_mode (MODE_POINTER_BOUNDS, name, file, line);
+   m->bytesize = bytesize;
+ }
  #define INT_MODE(N, Y) FRACTIONAL_INT_MODE (N, -1U, Y)
  #define FRACTIONAL_INT_MODE(N, B, Y) \
    make_int_mode (#N, B, Y, __FILE__, __LINE__)
@@@ -630,10 -644,10 +644,10 @@@ reset_float_format (const char *name, c
    m->format = format;
  }
  
- /* Partial integer modes are specified by relation to a full integer mode.
-    For now, we do not attempt to narrow down their bit sizes.  */
- #define PARTIAL_INT_MODE(M) \
-   make_partial_integer_mode (#M, "P" #M, -1U, __FILE__, __LINE__)
+ /* Partial integer modes are specified by relation to a full integer
+    mode.  */
+ #define PARTIAL_INT_MODE(M,PREC,NAME)                         \
+   make_partial_integer_mode (#M, #NAME, PREC, __FILE__, __LINE__)
  static void ATTRIBUTE_UNUSED
  make_partial_integer_mode (const char *base, const char *name,
                           unsigned int precision,
@@@ -670,7 -684,7 +684,7 @@@ make_vector_mode (enum mode_class bclas
    struct mode_data *v;
    enum mode_class vclass = vector_class (bclass);
    struct mode_data *component = find_mode (base);
-   char namebuf[8];
+   char namebuf[16];
  
    if (vclass == MODE_RANDOM)
      return;
@@@ -869,14 -883,14 +883,14 @@@ emit_max_int (void
        max = i->bytesize;
    if (max > mmax)
      mmax = max;
 -  printf ("#define MAX_BITSIZE_MODE_ANY_INT %d*BITS_PER_UNIT\n", mmax);
 +  printf ("#define MAX_BITSIZE_MODE_ANY_INT %d\n", mmax * MAX_BITS_PER_UNIT);
  
    mmax = 0;
    for (j = 0; j < MAX_MODE_CLASS; j++)
      for (i = modes[j]; i; i = i->next)
        if (mmax < i->bytesize)
        mmax = i->bytesize;
 -  printf ("#define MAX_BITSIZE_MODE_ANY_MODE %d*BITS_PER_UNIT\n", mmax);
 +  printf ("#define MAX_BITSIZE_MODE_ANY_MODE %d\n", mmax * MAX_BITS_PER_UNIT);
  }
  
  static void
@@@ -918,7 -932,7 +932,7 @@@ enum machine_mode\n{")
         end will try to use it for bitfields in structures and the
         like, which we do not want.  Only the target md file should
         generate BImode widgets.  */
-       if (first && first->precision == 1)
+       if (first && first->precision == 1 && c == MODE_INT)
        first = first->next;
  
        if (first && last)
@@@ -1188,7 -1202,7 +1202,7 @@@ emit_class_narrowest_mode (void
      /* Bleah, all this to get the comment right for MIN_MODE_INT.  */
      tagged_printf ("MIN_%s", mode_class_names[c],
                   modes[c]
-                  ? (modes[c]->precision != 1
+                  ? ((c != MODE_INT || modes[c]->precision != 1)
                      ? modes[c]->name
                      : (modes[c]->next
                         ? modes[c]->next->name
diff --combined gcc/gimple-fold.c
index 36d993ca5a8e96f9f3e36978a91636c0a0d275d5,b4da694b27bd1a74576ac2ebd99bdb6b267e2f2e..6ad5981cc1bd6b58f78ca021ab0395f179d2ce12
@@@ -26,6 -26,12 +26,12 @@@ along with GCC; see the file COPYING3
  #include "flags.h"
  #include "function.h"
  #include "dumpfile.h"
+ #include "bitmap.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-ssanames.h"
+ #include "tree-into-ssa.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "tree-ssa-propagate.h"
  #include "target.h"
@@@ -60,7 -66,7 +66,7 @@@ can_refer_decl_in_current_unit_p (tree 
  {
    struct varpool_node *vnode;
    struct cgraph_node *node;
-   symtab_node snode;
+   symtab_node *snode;
  
    if (DECL_ABSTRACT (decl))
      return false;
        || TREE_CODE (from_decl) != VAR_DECL
        || !DECL_EXTERNAL (from_decl)
        || (flag_ltrans
-         && symtab_get_node (from_decl)->symbol.in_other_partition))
+         && symtab_get_node (from_decl)->in_other_partition))
      return true;
    /* We are folding reference from external vtable.  The vtable may reffer
       to a symbol keyed to other compilation unit.  The other compilation
       unit may be in separate DSO and the symbol may be hidden.  */
    if (DECL_VISIBILITY_SPECIFIED (decl)
        && DECL_EXTERNAL (decl)
-       && (!(snode = symtab_get_node (decl)) || !snode->symbol.in_other_partition))
+       && (!(snode = symtab_get_node (decl)) || !snode->in_other_partition))
      return false;
    /* When function is public, we always can introduce new reference.
       Exception are the COMDAT functions where introducing a direct
           The second is important when devirtualization happens during final
           compilation stage when making a new reference no longer makes callee
           to be compiled.  */
-       if (!node || !node->symbol.definition || node->global.inlined_to)
+       if (!node || !node->definition || node->global.inlined_to)
        {
          gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
          return false;
    else if (TREE_CODE (decl) == VAR_DECL)
      {
        vnode = varpool_get_node (decl);
-       if (!vnode || !vnode->symbol.definition)
+       if (!vnode || !vnode->definition)
        {
          gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
          return false;
@@@ -1065,7 -1071,7 +1071,7 @@@ gimple_extract_devirt_binfo_from_cst (t
            continue;
  
          pos = int_bit_position (fld);
 -        size = tree_low_cst (DECL_SIZE (fld), 1);
 +        size = tree_to_uhwi (DECL_SIZE (fld));
          if (pos <= offset && (pos + size) > offset)
            break;
        }
@@@ -1142,7 -1148,7 +1148,7 @@@ gimple_fold_call (gimple_stmt_iterator 
          if (binfo)
            {
              HOST_WIDE_INT token
 -              = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
 +              = tree_to_hwi (OBJ_TYPE_REF_TOKEN (callee));
              tree fndecl = gimple_get_virt_method_for_binfo (token, binfo);
              if (fndecl)
                {
@@@ -2709,9 -2715,9 +2715,9 @@@ get_base_constructor (tree base, HOST_W
      {
        if (!integer_zerop (TREE_OPERAND (base, 1)))
        {
 -        if (!host_integerp (TREE_OPERAND (base, 1), 0))
 +        if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
            return NULL_TREE;
 -        *bit_offset += (mem_ref_offset (base).low
 +        *bit_offset += (mem_ref_offset (base).to_short_addr ()
                          * BITS_PER_UNIT);
        }
  
@@@ -2806,10 -2812,9 +2812,10 @@@ fold_array_ctor_reference (tree type, t
  {
    unsigned HOST_WIDE_INT cnt;
    tree cfield, cval;
 -  double_int low_bound, elt_size;
 -  double_int index, max_index;
 -  double_int access_index;
 +  offset_int low_bound;
 +  offset_int elt_size;
 +  offset_int index, max_index;
 +  offset_int access_index;
    tree domain_type = NULL_TREE, index_type = NULL_TREE;
    HOST_WIDE_INT inner_offset;
  
        /* Static constructors for variably sized objects makes no sense.  */
        gcc_assert (TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST);
        index_type = TREE_TYPE (TYPE_MIN_VALUE (domain_type));
 -      low_bound = tree_to_double_int (TYPE_MIN_VALUE (domain_type));
 +      low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type));
      }
    else
 -    low_bound = double_int_zero;
 +    low_bound = 0;
    /* Static constructors for variably sized objects makes no sense.  */
    gcc_assert (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))))
              == INTEGER_CST);
 -  elt_size =
 -    tree_to_double_int (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))));
 -
 +  elt_size = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))));
  
    /* We can handle only constantly sized accesses that are known to not
       be larger than size of array element.  */
    if (!TYPE_SIZE_UNIT (type)
        || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
 -      || elt_size.slt (tree_to_double_int (TYPE_SIZE_UNIT (type))))
 +      || wi::lts_p (elt_size, wi::to_offset (TYPE_SIZE_UNIT (type))))
      return NULL_TREE;
  
    /* Compute the array index we look for.  */
 -  access_index = double_int::from_uhwi (offset / BITS_PER_UNIT)
 -               .udiv (elt_size, TRUNC_DIV_EXPR);
 +  access_index = wi::udiv_trunc (offset_int (offset / BITS_PER_UNIT),
 +                               elt_size);
    access_index += low_bound;
    if (index_type)
 -    access_index = access_index.ext (TYPE_PRECISION (index_type),
 -                                   TYPE_UNSIGNED (index_type));
 +    access_index = wi::ext (access_index, TYPE_PRECISION (index_type),
 +                          TYPE_SIGN (index_type));
  
    /* And offset within the access.  */
    inner_offset = offset % (elt_size.to_uhwi () * BITS_PER_UNIT);
    if (inner_offset + size > elt_size.to_uhwi () * BITS_PER_UNIT)
      return NULL_TREE;
  
 -  index = low_bound - double_int_one;
 +  index = low_bound - 1;
    if (index_type)
 -    index = index.ext (TYPE_PRECISION (index_type), TYPE_UNSIGNED (index_type));
 +    index = wi::ext (index, TYPE_PRECISION (index_type),
 +                   TYPE_SIGN (index_type));
  
    FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
      {
        if (cfield)
        {
          if (TREE_CODE (cfield) == INTEGER_CST)
 -          max_index = index = tree_to_double_int (cfield);
 +          max_index = index = wi::to_offset (cfield);
          else
            {
              gcc_assert (TREE_CODE (cfield) == RANGE_EXPR);
 -            index = tree_to_double_int (TREE_OPERAND (cfield, 0));
 -            max_index = tree_to_double_int (TREE_OPERAND (cfield, 1));
 +            index = wi::to_offset (TREE_OPERAND (cfield, 0));
 +            max_index = wi::to_offset (TREE_OPERAND (cfield, 1));
            }
        }
        else
        {
 -        index += double_int_one;
 +        index += 1;
          if (index_type)
 -          index = index.ext (TYPE_PRECISION (index_type),
 -                             TYPE_UNSIGNED (index_type));
 +          index = wi::ext (index, TYPE_PRECISION (index_type),
 +                           TYPE_SIGN (index_type));
          max_index = index;
        }
  
        /* Do we have match?  */
 -      if (access_index.cmp (index, 1) >= 0
 -        && access_index.cmp (max_index, 1) <= 0)
 +      if (wi::cmpu (access_index, index) >= 0
 +        && wi::cmpu (access_index, max_index) <= 0)
        return fold_ctor_reference (type, cval, inner_offset, size,
                                    from_decl);
      }
@@@ -2912,9 -2918,10 +2918,9 @@@ fold_nonarray_ctor_reference (tree type
        tree byte_offset = DECL_FIELD_OFFSET (cfield);
        tree field_offset = DECL_FIELD_BIT_OFFSET (cfield);
        tree field_size = DECL_SIZE (cfield);
 -      double_int bitoffset;
 -      double_int byte_offset_cst = tree_to_double_int (byte_offset);
 -      double_int bits_per_unit_cst = double_int::from_uhwi (BITS_PER_UNIT);
 -      double_int bitoffset_end, access_end;
 +      offset_int bitoffset;
 +      offset_int byte_offset_cst = wi::to_offset (byte_offset);
 +      offset_int bitoffset_end, access_end;
  
        /* Variable sized objects in static constructors makes no sense,
         but field_size can be NULL for flexible array members.  */
                      : TREE_CODE (TREE_TYPE (cfield)) == ARRAY_TYPE));
  
        /* Compute bit offset of the field.  */
 -      bitoffset = tree_to_double_int (field_offset)
 -                + byte_offset_cst * bits_per_unit_cst;
 +      bitoffset = (wi::to_offset (field_offset)
 +                 + byte_offset_cst * BITS_PER_UNIT);
        /* Compute bit offset where the field ends.  */
        if (field_size != NULL_TREE)
 -      bitoffset_end = bitoffset + tree_to_double_int (field_size);
 +      bitoffset_end = bitoffset + wi::to_offset (field_size);
        else
 -      bitoffset_end = double_int_zero;
 +      bitoffset_end = 0;
  
 -      access_end = double_int::from_uhwi (offset)
 -                 + double_int::from_uhwi (size);
 +      access_end = offset_int (offset) + size;
  
        /* Is there any overlap between [OFFSET, OFFSET+SIZE) and
         [BITOFFSET, BITOFFSET_END)?  */
 -      if (access_end.cmp (bitoffset, 0) > 0
 +      if (wi::cmps (access_end, bitoffset) > 0
          && (field_size == NULL_TREE
 -            || double_int::from_uhwi (offset).slt (bitoffset_end)))
 +            || wi::lts_p (offset, bitoffset_end)))
        {
 -        double_int inner_offset = double_int::from_uhwi (offset) - bitoffset;
 +        offset_int inner_offset = offset_int (offset) - bitoffset;
          /* We do have overlap.  Now see if field is large enough to
             cover the access.  Give up for accesses spanning multiple
             fields.  */
 -        if (access_end.cmp (bitoffset_end, 0) > 0)
 +        if (wi::cmps (access_end, bitoffset_end) > 0)
            return NULL_TREE;
 -        if (double_int::from_uhwi (offset).slt (bitoffset))
 +        if (wi::lts_p (offset, bitoffset))
            return NULL_TREE;
          return fold_ctor_reference (type, cval,
                                      inner_offset.to_uhwi (), size,
@@@ -3037,42 -3045,38 +3043,42 @@@ fold_const_aggregate_ref_1 (tree t, tre
          && (idx = (*valueize) (TREE_OPERAND (t, 1)))
          && TREE_CODE (idx) == INTEGER_CST)
        {
 -        tree low_bound, unit_size;
 -        double_int doffset;
 +        tree low_bound = array_ref_low_bound (t); 
 +        tree unit_size = array_ref_element_size (t);
  
          /* If the resulting bit-offset is constant, track it.  */
 -        if ((low_bound = array_ref_low_bound (t),
 -             TREE_CODE (low_bound) == INTEGER_CST)
 -            && (unit_size = array_ref_element_size (t),
 -                host_integerp (unit_size, 1))
 -            && (doffset = (TREE_INT_CST (idx) - TREE_INT_CST (low_bound))
 -                          .sext (TYPE_PRECISION (TREE_TYPE (idx))),
 -                doffset.fits_shwi ()))
 +        if ((TREE_CODE (low_bound) == INTEGER_CST)
 +            && (tree_fits_uhwi_p (unit_size)))
            {
 -            offset = doffset.to_shwi ();
 -            offset *= TREE_INT_CST_LOW (unit_size);
 -            offset *= BITS_PER_UNIT;
 -
 -            base = TREE_OPERAND (t, 0);
 -            ctor = get_base_constructor (base, &offset, valueize);
 -            /* Empty constructor.  Always fold to 0.  */
 -            if (ctor == error_mark_node)
 -              return build_zero_cst (TREE_TYPE (t));
 -            /* Out of bound array access.  Value is undefined,
 -               but don't fold.  */
 -            if (offset < 0)
 -              return NULL_TREE;
 -            /* We can not determine ctor.  */
 -            if (!ctor)
 -              return NULL_TREE;
 -            return fold_ctor_reference (TREE_TYPE (t), ctor, offset,
 -                                        TREE_INT_CST_LOW (unit_size)
 -                                        * BITS_PER_UNIT,
 -                                        base);
 +            offset_int woffset
 +              = wi::sext (wi::to_offset (idx) - wi::to_offset (low_bound),
 +                          TYPE_PRECISION (TREE_TYPE (idx)));
 +            
 +            if (wi::fits_shwi_p (woffset))
 +              {
 +                offset = woffset.to_shwi ();
 +                /* TODO: This code seems wrong, multiply then check
 +                   to see if it fits.  */
 +                offset *= tree_to_hwi (unit_size);
 +                offset *= BITS_PER_UNIT;
 +                
 +                base = TREE_OPERAND (t, 0);
 +                ctor = get_base_constructor (base, &offset, valueize);
 +                /* Empty constructor.  Always fold to 0.  */
 +                if (ctor == error_mark_node)
 +                  return build_zero_cst (TREE_TYPE (t));
 +                /* Out of bound array access.  Value is undefined,
 +                   but don't fold.  */
 +                if (offset < 0)
 +                  return NULL_TREE;
 +                /* We can not determine ctor.  */
 +                if (!ctor)
 +                  return NULL_TREE;
 +                return fold_ctor_reference (TREE_TYPE (t), ctor, offset,
 +                                            tree_to_uhwi (unit_size)
 +                                            * BITS_PER_UNIT,
 +                                            base);
 +              }
            }
        }
        /* Fallthru.  */
@@@ -3142,7 -3146,7 +3148,7 @@@ gimple_get_virt_method_for_binfo (HOST_
  
    if (TREE_CODE (v) == POINTER_PLUS_EXPR)
      {
 -      offset = tree_low_cst (TREE_OPERAND (v, 1), 1) * BITS_PER_UNIT;
 +      offset = tree_to_uhwi (TREE_OPERAND (v, 1)) * BITS_PER_UNIT;
        v = TREE_OPERAND (v, 0);
      }
    else
        return NULL_TREE;
      }
    gcc_checking_assert (TREE_CODE (TREE_TYPE (v)) == ARRAY_TYPE);
 -  size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (v))), 1);
 +  size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (v))));
    offset += token * size;
    fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), init,
                            offset, size, v);
@@@ -3287,7 -3291,7 +3293,7 @@@ gimple_val_nonnegative_real_p (tree val
              arg1 = gimple_call_arg (def_stmt, 1);
  
              if (TREE_CODE (arg1) == INTEGER_CST
 -                && (TREE_INT_CST_LOW (arg1) & 1) == 0)
 +                && (tree_to_hwi (arg1) & 1) == 0)
                return true;
  
              break;
                  if ((n & 1) == 0)
                    {
                      REAL_VALUE_TYPE cint;
 -                    real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
 +                    real_from_integer (&cint, VOIDmode, n, SIGNED);
                      if (real_identical (&c, &cint))
                        return true;
                    }
@@@ -3392,12 -3396,12 +3398,12 @@@ gimple_fold_indirect_ref (tree t
        if (TREE_CODE (addr) == ADDR_EXPR
          && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE
          && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype)))
 -        && host_integerp (off, 1))
 +        && tree_fits_uhwi_p (off))
        {
 -          unsigned HOST_WIDE_INT offset = tree_low_cst (off, 1);
 +          unsigned HOST_WIDE_INT offset = tree_to_uhwi (off);
            tree part_width = TYPE_SIZE (type);
            unsigned HOST_WIDE_INT part_widthi
 -            = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
 +            = tree_to_shwi (part_width) / BITS_PER_UNIT;
            unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
            tree index = bitsize_int (indexi);
            if (offset / part_widthi
          || DECL_P (TREE_OPERAND (addr, 0)))
        return fold_build2 (MEM_REF, type,
                            addr,
 -                          build_int_cst_wide (ptype,
 -                                              TREE_INT_CST_LOW (off),
 -                                              TREE_INT_CST_HIGH (off)));
 +                          wide_int_to_tree (ptype, off));
      }
  
    /* *(foo *)fooarrptr => (*fooarrptr)[0] */
index a45dd535d9523cb642263335b85ad90939516840,6842213199af8f1edcdce0176587aaee08b6f130..c95b9c463571d41531354fcc5a1de07603a5ee9d
@@@ -27,9 -27,13 +27,13 @@@ along with GCC; see the file COPYING3
  #include "diagnostic.h"
  #include "gimple-pretty-print.h"
  #include "hashtab.h"
- #include "tree-ssa.h"
- #include "dumpfile.h" /* for dump_flags */
+ #include "bitmap.h"
  #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-ssanames.h"
+ #include "dumpfile.h" /* for dump_flags */
  #include "value-prof.h"
  #include "trans-mem.h"
  
@@@ -535,11 -539,12 +539,12 @@@ dump_gimple_assign (pretty_printer *buf
  static void
  dump_gimple_return (pretty_printer *buffer, gimple gs, int spc, int flags)
  {
-   tree t;
+   tree t, t2;
  
    t = gimple_return_retval (gs);
+   t2 = gimple_return_retbnd (gs);
    if (flags & TDF_RAW)
-     dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, t);
+     dump_gimple_fmt (buffer, spc, flags, "%G <%T %T>", gs, t, t2);
    else
      {
        pp_string (buffer, "return");
          pp_space (buffer);
          dump_generic_node (buffer, t, spc, flags, false);
        }
+       if (t2)
+       {
+         pp_string (buffer, ", ");
+         dump_generic_node (buffer, t2, spc, flags, false);
+       }
        pp_semicolon (buffer);
      }
  }
@@@ -713,7 -723,7 +723,7 @@@ dump_gimple_call (pretty_printer *buffe
        pp_string (buffer, " [ ");
  
        /* Get the transaction code properties.  */
 -      props = TREE_INT_CST_LOW (t);
 +      props = tree_to_hwi (t);
  
        if (props & PR_INSTRUMENTEDCODE)
        pp_string (buffer, "instrumentedCode ");
@@@ -1714,7 -1724,7 +1724,7 @@@ dump_ssaname_info (pretty_printer *buff
      {
        unsigned int align, misalign;
        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (node);
-       pp_string (buffer, "PT = ");
+       pp_string (buffer, "PT = ");
        pp_points_to_solution (buffer, &pi->pt);
        newline_and_indent (buffer, spc);
        if (get_ptr_info_alignment (pi, &align, &misalign))
          pp_printf (buffer, "# ALIGN = %u, MISALIGN = %u", align, misalign);
          newline_and_indent (buffer, spc);
        }
-       pp_string (buffer, "# ");
      }
  
    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  VR_VARYING");
+       pp_printf (buffer, "# RANGE VR_VARYING");
        else if (range_type == VR_RANGE || range_type == VR_ANTI_RANGE)
        {
          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);
      }
  }
  
  
  /* Dump a PHI node PHI.  BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1.
     The caller is responsible for calling pp_flush on BUFFER to finalize
-    pretty printer.  */
+    pretty printer.  If COMMENT is true, print this after #.  */
  
  static void
- dump_gimple_phi (pretty_printer *buffer, gimple phi, int spc, int flags)
+ dump_gimple_phi (pretty_printer *buffer, gimple phi, int spc, bool comment,
+                int flags)
  {
    size_t i;
    tree lhs = gimple_phi_result (phi);
    if (flags & TDF_ALIAS)
      dump_ssaname_info (buffer, lhs, spc);
  
+   if (comment)
+     pp_string (buffer, "# ");
    if (flags & TDF_RAW)
      dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
                     gimple_phi_result (phi));
@@@ -2095,7 -2120,7 +2116,7 @@@ pp_gimple_stmt_1 (pretty_printer *buffe
        break;
  
      case GIMPLE_PHI:
-       dump_gimple_phi (buffer, gs, spc, flags);
+       dump_gimple_phi (buffer, gs, spc, false, flags);
        break;
  
      case GIMPLE_OMP_PARALLEL:
@@@ -2271,8 -2296,7 +2292,7 @@@ dump_phi_nodes (pretty_printer *buffer
        if (!virtual_operand_p (gimple_phi_result (phi)) || (flags & TDF_VOPS))
          {
            INDENT (indent);
-           pp_string (buffer, "# ");
-           dump_gimple_phi (buffer, phi, indent, flags);
+         dump_gimple_phi (buffer, phi, indent, true, flags);
            pp_newline (buffer);
          }
      }
index 4d9c1f8d68dc2cefbfd54ebec9c26fd4aa09f36c,88afc91200fa93f9064f04039685bf55c6065e4f..69680b285853b35a5aa19fe4264ab740eb2ccec1
@@@ -42,14 -42,17 +42,18 @@@ along with GCC; see the file COPYING3
  #include "tree-pass.h"
  #include "cfgloop.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
  #include "domwalk.h"
  #include "pointer-set.h"
  #include "expmed.h"
  #include "params.h"
  #include "hash-table.h"
  #include "tree-ssa-address.h"
 +#include "wide-int-print.h"
  \f
  /* Information about a strength reduction candidate.  Each statement
     in the candidate table represents an expression of one of the
@@@ -231,7 -234,7 +235,7 @@@ struct slsr_cand_
    tree stride;
  
    /* The index constant i.  */
 -  double_int index;
 +  widest_int index;
  
    /* The type of the candidate.  This is normally the type of base_expr,
       but casts may have occurred when combining feeding instructions.
@@@ -306,7 -309,7 +310,7 @@@ typedef const struct cand_chain_d *cons
  struct incr_info_d
  {
    /* The increment that relates a candidate to its basis.  */
 -  double_int incr;
 +  widest_int incr;
  
    /* How many times the increment occurs in the candidate tree.  */
    unsigned count;
@@@ -555,7 -558,7 +559,7 @@@ record_potential_basis (slsr_cand_t c
  
  static slsr_cand_t
  alloc_cand_and_find_basis (enum cand_kind kind, gimple gs, tree base, 
 -                         double_int index, tree stride, tree ctype,
 +                         const widest_int &index, tree stride, tree ctype,
                           unsigned savings)
  {
    slsr_cand_t c = (slsr_cand_t) obstack_alloc (&cand_obstack,
@@@ -604,8 -607,8 +608,8 @@@ stmt_cost (gimple gs, bool speed
      case MULT_EXPR:
        rhs2 = gimple_assign_rhs2 (gs);
  
 -      if (host_integerp (rhs2, 0))
 -      return mult_by_coeff_cost (TREE_INT_CST_LOW (rhs2), lhs_mode, speed);
 +      if (tree_fits_shwi_p (rhs2))
 +      return mult_by_coeff_cost (tree_to_shwi (rhs2), lhs_mode, speed);
  
        gcc_assert (TREE_CODE (rhs1) != INTEGER_CST);
        return mul_cost (speed, lhs_mode);
@@@ -746,8 -749,8 +750,8 @@@ slsr_process_phi (gimple phi, bool spee
       CAND_PHI.  */
    base_type = TREE_TYPE (arg0_base);
  
 -  c = alloc_cand_and_find_basis (CAND_PHI, phi, arg0_base, double_int_zero,
 -                               integer_one_node, base_type, savings);
 +  c = alloc_cand_and_find_basis (CAND_PHI, phi, arg0_base, 
 +                               0, integer_one_node, base_type, savings);
  
    /* Add the candidate to the statement-candidate mapping.  */
    add_cand_for_stmt (phi, c);
     int (i * S).
     Otherwise, just return double int zero.  */
  
 -static double_int
 +static widest_int
  backtrace_base_for_ref (tree *pbase)
  {
    tree base_in = *pbase;
      base_in = get_unwidened (base_in, NULL_TREE);
  
    if (TREE_CODE (base_in) != SSA_NAME)
 -    return tree_to_double_int (integer_zero_node);
 +    return 0;
  
    base_cand = base_cand_from_table (base_in);
  
    while (base_cand && base_cand->kind != CAND_PHI)
      {
        if (base_cand->kind == CAND_ADD
 -        && base_cand->index.is_one ()
 +        && base_cand->index == 1
          && TREE_CODE (base_cand->stride) == INTEGER_CST)
        {
          /* X = B + (1 * S), S is integer constant.  */
          *pbase = base_cand->base_expr;
 -        return tree_to_double_int (base_cand->stride);
 +        return wi::to_widest (base_cand->stride);
        }
        else if (base_cand->kind == CAND_ADD
               && TREE_CODE (base_cand->stride) == INTEGER_CST
        base_cand = NULL;
      }
  
 -  return tree_to_double_int (integer_zero_node);
 +  return 0;
  }
  
  /* Look for the following pattern:
      *PINDEX:   C1 + (C2 * C3) + C4 + (C5 * C3)  */
  
  static bool
 -restructure_reference (tree *pbase, tree *poffset, double_int *pindex,
 +restructure_reference (tree *pbase, tree *poffset, widest_int *pindex,
                       tree *ptype)
  {
    tree base = *pbase, offset = *poffset;
 -  double_int index = *pindex;
 -  double_int bpu = double_int::from_uhwi (BITS_PER_UNIT);
 -  tree mult_op0, mult_op1, t1, t2, type;
 -  double_int c1, c2, c3, c4, c5;
 +  widest_int index = *pindex;
 +  tree mult_op0, t1, t2, type;
 +  widest_int c1, c2, c3, c4, c5;
  
    if (!base
        || !offset
        || TREE_CODE (base) != MEM_REF
        || TREE_CODE (offset) != MULT_EXPR
        || TREE_CODE (TREE_OPERAND (offset, 1)) != INTEGER_CST
 -      || !index.umod (bpu, FLOOR_MOD_EXPR).is_zero ())
 +      || wi::umod_floor (index, BITS_PER_UNIT) != 0)
      return false;
  
    t1 = TREE_OPERAND (base, 0);
 -  c1 = mem_ref_offset (base);
 +  c1 = widest_int::from (mem_ref_offset (base), SIGNED);
    type = TREE_TYPE (TREE_OPERAND (base, 1));
  
    mult_op0 = TREE_OPERAND (offset, 0);
 -  mult_op1 = TREE_OPERAND (offset, 1);
 -
 -  c3 = tree_to_double_int (mult_op1);
 +  c3 = wi::to_widest (TREE_OPERAND (offset, 1));
  
    if (TREE_CODE (mult_op0) == PLUS_EXPR)
  
      if (TREE_CODE (TREE_OPERAND (mult_op0, 1)) == INTEGER_CST)
        {
        t2 = TREE_OPERAND (mult_op0, 0);
 -      c2 = tree_to_double_int (TREE_OPERAND (mult_op0, 1));
 +      c2 = wi::to_widest (TREE_OPERAND (mult_op0, 1));
        }
      else
        return false;
      if (TREE_CODE (TREE_OPERAND (mult_op0, 1)) == INTEGER_CST)
        {
        t2 = TREE_OPERAND (mult_op0, 0);
 -      c2 = -tree_to_double_int (TREE_OPERAND (mult_op0, 1));
 +      c2 = -wi::to_widest (TREE_OPERAND (mult_op0, 1));
        }
      else
        return false;
    else
      {
        t2 = mult_op0;
 -      c2 = double_int_zero;
 +      c2 = 0;
      }
  
 -  c4 = index.udiv (bpu, FLOOR_DIV_EXPR);
 +  c4 = wi::udiv_floor (index, BITS_PER_UNIT);
    c5 = backtrace_base_for_ref (&t2);
  
    *pbase = t1;
    *poffset = fold_build2 (MULT_EXPR, sizetype, fold_convert (sizetype, t2),
 -                        double_int_to_tree (sizetype, c3));
 +                        wide_int_to_tree (sizetype, c3));
    *pindex = c1 + c2 * c3 + c4 + c5 * c3;
    *ptype = type;
  
@@@ -910,6 -916,7 +914,6 @@@ slsr_process_ref (gimple gs
    HOST_WIDE_INT bitsize, bitpos;
    enum machine_mode mode;
    int unsignedp, volatilep;
 -  double_int index;
    slsr_cand_t c;
  
    if (gimple_vdef (gs))
  
    base = get_inner_reference (ref_expr, &bitsize, &bitpos, &offset, &mode,
                              &unsignedp, &volatilep, false);
 -  index = double_int::from_uhwi (bitpos);
 +  widest_int index = bitpos;
  
    if (!restructure_reference (&base, &offset, &index, &type))
      return;
@@@ -946,7 -953,7 +950,7 @@@ static slsr_cand_
  create_mul_ssa_cand (gimple gs, tree base_in, tree stride_in, bool speed)
  {
    tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
 -  double_int index;
 +  widest_int index;
    unsigned savings = 0;
    slsr_cand_t c;
    slsr_cand_t base_cand = base_cand_from_table (base_in);
             ============================
             X = B + ((i' * S) * Z)  */
          base = base_cand->base_expr;
 -        index = base_cand->index * tree_to_double_int (base_cand->stride);
 +        index = base_cand->index * wi::to_widest (base_cand->stride);
          stride = stride_in;
          ctype = base_cand->cand_type;
          if (has_single_use (base_in))
        /* No interpretations had anything useful to propagate, so
         produce X = (Y + 0) * Z.  */
        base = base_in;
 -      index = double_int_zero;
 +      index = 0;
        stride = stride_in;
        ctype = TREE_TYPE (base_in);
      }
@@@ -1016,7 -1023,7 +1020,7 @@@ static slsr_cand_
  create_mul_imm_cand (gimple gs, tree base_in, tree stride_in, bool speed)
  {
    tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
 -  double_int index, temp;
 +  widest_int index, temp;
    unsigned savings = 0;
    slsr_cand_t c;
    slsr_cand_t base_cand = base_cand_from_table (base_in);
             X = (B + i') * (S * c)  */
          base = base_cand->base_expr;
          index = base_cand->index;
 -        temp = tree_to_double_int (base_cand->stride)
 -               * tree_to_double_int (stride_in);
 -        stride = double_int_to_tree (TREE_TYPE (stride_in), temp);
 +        temp = wi::to_widest (base_cand->stride) * wi::to_widest (stride_in);
 +        stride = wide_int_to_tree (TREE_TYPE (stride_in), temp);
          ctype = base_cand->cand_type;
          if (has_single_use (base_in))
            savings = (base_cand->dead_savings 
                       + stmt_cost (base_cand->cand_stmt, speed));
        }
        else if (base_cand->kind == CAND_ADD
 -             && base_cand->index.is_one ()
 +             && base_cand->index == 1
               && TREE_CODE (base_cand->stride) == INTEGER_CST)
        {
          /* Y = B + (1 * S), S constant
             ===========================
             X = (B + S) * c  */
          base = base_cand->base_expr;
 -        index = tree_to_double_int (base_cand->stride);
 +        index = wi::to_widest (base_cand->stride);
          stride = stride_in;
          ctype = base_cand->cand_type;
          if (has_single_use (base_in))
        /* No interpretations had anything useful to propagate, so
         produce X = (Y + 0) * c.  */
        base = base_in;
 -      index = double_int_zero;
 +      index = 0;
        stride = stride_in;
        ctype = TREE_TYPE (base_in);
      }
@@@ -1146,7 -1154,7 +1150,7 @@@ create_add_ssa_cand (gimple gs, tree ba
                     bool subtract_p, bool speed)
  {
    tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL;
 -  double_int index;
 +  widest_int index;
    unsigned savings = 0;
    slsr_cand_t c;
    slsr_cand_t base_cand = base_cand_from_table (base_in);
    while (addend_cand && !base && addend_cand->kind != CAND_PHI)
      {
        if (addend_cand->kind == CAND_MULT
 -        && addend_cand->index.is_zero ()
 +        && addend_cand->index == 0
          && TREE_CODE (addend_cand->stride) == INTEGER_CST)
        {
          /* Z = (B + 0) * S, S constant
             ===========================
             X = Y + ((+/-1 * S) * B)  */
          base = base_in;
 -        index = tree_to_double_int (addend_cand->stride);
 +        index = wi::to_widest (addend_cand->stride);
          if (subtract_p)
            index = -index;
          stride = addend_cand->base_expr;
    while (base_cand && !base && base_cand->kind != CAND_PHI)
      {
        if (base_cand->kind == CAND_ADD
 -        && (base_cand->index.is_zero ()
 +        && (base_cand->index == 0
              || operand_equal_p (base_cand->stride,
                                  integer_zero_node, 0)))
        {
             ============================
             X = B + (+/-1 * Z)  */
          base = base_cand->base_expr;
 -        index = subtract_p ? double_int_minus_one : double_int_one;
 +        index = subtract_p ? -1 : 1;
          stride = addend_in;
          ctype = base_cand->cand_type;
          if (has_single_use (base_in))
          while (subtrahend_cand && !base && subtrahend_cand->kind != CAND_PHI)
            {
              if (subtrahend_cand->kind == CAND_MULT
 -                && subtrahend_cand->index.is_zero ()
 +                && subtrahend_cand->index == 0
                  && TREE_CODE (subtrahend_cand->stride) == INTEGER_CST)
                {
                  /* Z = (B + 0) * S, S constant
                     ===========================
                     Value:  X = Y + ((-1 * S) * B)  */
                  base = base_in;
 -                index = tree_to_double_int (subtrahend_cand->stride);
 +                index = wi::to_widest (subtrahend_cand->stride);
                  index = -index;
                  stride = subtrahend_cand->base_expr;
                  ctype = TREE_TYPE (base_in);
        /* No interpretations had anything useful to propagate, so
         produce X = Y + (1 * Z).  */
        base = base_in;
 -      index = subtract_p ? double_int_minus_one : double_int_one;
 +      index = subtract_p ? -1 : 1;
        stride = addend_in;
        ctype = TREE_TYPE (base_in);
      }
     about BASE_IN into the new candidate.  Return the new candidate.  */
  
  static slsr_cand_t
 -create_add_imm_cand (gimple gs, tree base_in, double_int index_in, bool speed)
 +create_add_imm_cand (gimple gs, tree base_in, const widest_int &index_in,
 +                   bool speed)
  {
    enum cand_kind kind = CAND_ADD;
    tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
 -  double_int index, multiple;
 +  widest_int index, multiple;
    unsigned savings = 0;
    slsr_cand_t c;
    slsr_cand_t base_cand = base_cand_from_table (base_in);
  
    while (base_cand && !base && base_cand->kind != CAND_PHI)
      {
 -      bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (base_cand->stride));
 +      signop sign = TYPE_SIGN (TREE_TYPE (base_cand->stride));
  
        if (TREE_CODE (base_cand->stride) == INTEGER_CST
 -        && index_in.multiple_of (tree_to_double_int (base_cand->stride),
 -                                 unsigned_p, &multiple))
 +        && wi::multiple_of_p (index_in, wi::to_widest (base_cand->stride),
 +                              sign, &multiple))
        {
          /* Y = (B + i') * S, S constant, c = kS for some integer k
             X = Y + c
@@@ -1358,8 -1365,10 +1362,8 @@@ slsr_process_add (gimple gs, tree rhs1
      }
    else
      {
 -      double_int index;
 -
        /* Record an interpretation for the add-immediate.  */
 -      index = tree_to_double_int (rhs2);
 +      widest_int index = wi::to_widest (rhs2);
        if (subtract_p)
        index = -index;
  
@@@ -1507,10 -1516,10 +1511,10 @@@ slsr_process_cast (gimple gs, tree rhs1
         The first of these is somewhat arbitrary, but the choice of
         1 for the stride simplifies the logic for propagating casts
         into their uses.  */
 -      c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1, double_int_zero,
 -                                   integer_one_node, ctype, 0);
 -      c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1, double_int_zero,
 -                                    integer_one_node, ctype, 0);
 +      c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1, 
 +                                   0, integer_one_node, ctype, 0);
 +      c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1, 
 +                                    0, integer_one_node, ctype, 0);
        c->next_interp = c2->cand_num;
      }
  
@@@ -1564,10 -1573,10 +1568,10 @@@ slsr_process_copy (gimple gs, tree rhs1
         The first of these is somewhat arbitrary, but the choice of
         1 for the stride simplifies the logic for propagating casts
         into their uses.  */
 -      c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1, double_int_zero,
 -                                   integer_one_node, TREE_TYPE (rhs1), 0);
 -      c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1, double_int_zero,
 -                                    integer_one_node, TREE_TYPE (rhs1), 0);
 +      c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1, 
 +                                   0, integer_one_node, TREE_TYPE (rhs1), 0);
 +      c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1, 
 +                                    0, integer_one_node, TREE_TYPE (rhs1), 0);
        c->next_interp = c2->cand_num;
      }
  
@@@ -1684,7 -1693,7 +1688,7 @@@ dump_candidate (slsr_cand_t c
        fputs ("     MULT : (", dump_file);
        print_generic_expr (dump_file, c->base_expr, 0);
        fputs (" + ", dump_file);
 -      dump_double_int (dump_file, c->index, false);
 +      print_decs (c->index, dump_file);
        fputs (") * ", dump_file);
        print_generic_expr (dump_file, c->stride, 0);
        fputs (" : ", dump_file);
        fputs ("     ADD  : ", dump_file);
        print_generic_expr (dump_file, c->base_expr, 0);
        fputs (" + (", dump_file);
 -      dump_double_int (dump_file, c->index, false);
 +      print_decs (c->index, dump_file);
        fputs (" * ", dump_file);
        print_generic_expr (dump_file, c->stride, 0);
        fputs (") : ", dump_file);
        fputs (" + (", dump_file);
        print_generic_expr (dump_file, c->stride, 0);
        fputs (") + ", dump_file);
 -      dump_double_int (dump_file, c->index, false);
 +      print_decs (c->index, dump_file);
        fputs (" : ", dump_file);
        break;
      case CAND_PHI:
@@@ -1783,7 -1792,7 +1787,7 @@@ dump_incr_vec (void
        for (i = 0; i < incr_vec_len; i++)
        {
          fprintf (dump_file, "%3d  increment:   ", i);
 -        dump_double_int (dump_file, incr_vec[i].incr, false);
 +        print_decs (incr_vec[i].incr, dump_file);
          fprintf (dump_file, "\n     count:       %d", incr_vec[i].count);
          fprintf (dump_file, "\n     cost:        %d", incr_vec[i].cost);
          fputs ("\n     initializer: ", dump_file);
@@@ -1814,7 -1823,7 +1818,7 @@@ replace_ref (tree *expr, slsr_cand_t c
    add_expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (c->base_expr),
                          c->base_expr, c->stride);
    mem_ref = fold_build2 (MEM_REF, acc_type, add_expr,
 -                       double_int_to_tree (c->cand_type, c->index));
 +                       wide_int_to_tree (c->cand_type, c->index));
  
    /* Gimplify the base addressing expression for the new MEM_REF tree.  */
    gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
@@@ -1869,7 -1878,7 +1873,7 @@@ phi_dependent_cand_p (slsr_cand_t c
  /* Calculate the increment required for candidate C relative to 
     its basis.  */
  
 -static double_int
 +static widest_int
  cand_increment (slsr_cand_t c)
  {
    slsr_cand_t basis;
     for this candidate, return the absolute value of that increment
     instead.  */
  
 -static inline double_int
 +static inline widest_int
  cand_abs_increment (slsr_cand_t c)
  {
 -  double_int increment = cand_increment (c);
 +  widest_int increment = cand_increment (c);
  
 -  if (!address_arithmetic_p && increment.is_negative ())
 +  if (!address_arithmetic_p && wi::neg_p (increment))
      increment = -increment;
  
    return increment;
@@@ -1916,7 -1925,7 +1920,7 @@@ cand_already_replaced (slsr_cand_t c
     replace_conditional_candidate.  */
  
  static void
 -replace_mult_candidate (slsr_cand_t c, tree basis_name, double_int bump)
 +replace_mult_candidate (slsr_cand_t c, tree basis_name, widest_int bump)
  {
    tree target_type = TREE_TYPE (gimple_assign_lhs (c->cand_stmt));
    enum tree_code cand_code = gimple_assign_rhs_code (c->cand_stmt);
       in this case.  This does not affect siblings or dependents
       of C.  Restriction to signed HWI is conservative for unsigned
       types but allows for safe negation without twisted logic.  */
 -  if (bump.fits_shwi ()
 +  if (wi::fits_shwi_p (bump)
        && bump.to_shwi () != HOST_WIDE_INT_MIN
        /* It is not useful to replace casts, copies, or adds of
         an SSA name and a constant.  */
         types, introduce a cast.  */
        if (!useless_type_conversion_p (target_type, TREE_TYPE (basis_name)))
        basis_name = introduce_cast_before_cand (c, target_type, basis_name);
 -      if (bump.is_negative ())
 +      if (wi::neg_p (bump))
        {
          code = MINUS_EXPR;
          bump = -bump;
        }
  
 -      bump_tree = double_int_to_tree (target_type, bump);
 +      bump_tree = wide_int_to_tree (target_type, bump);
  
        if (dump_file && (dump_flags & TDF_DETAILS))
        {
          print_gimple_stmt (dump_file, c->cand_stmt, 0, 0);
        }
  
 -      if (bump.is_zero ())
 +      if (bump == 0)
        {
          tree lhs = gimple_assign_lhs (c->cand_stmt);
          gimple copy_stmt = gimple_build_assign (lhs, basis_name);
@@@ -2019,12 -2028,14 +2023,12 @@@ static voi
  replace_unconditional_candidate (slsr_cand_t c)
  {
    slsr_cand_t basis;
 -  double_int stride, bump;
  
    if (cand_already_replaced (c))
      return;
  
    basis = lookup_cand (c->basis);
 -  stride = tree_to_double_int (c->stride);
 -  bump = cand_increment (c) * stride;
 +  widest_int bump = cand_increment (c) * wi::to_widest (c->stride);
  
    replace_mult_candidate (c, gimple_assign_lhs (basis->cand_stmt), bump);
  }
     MAX_INCR_VEC_LEN increments have been found.  */
  
  static inline int
 -incr_vec_index (double_int increment)
 +incr_vec_index (widest_int increment)
  {
    unsigned i;
    
  
  static tree
  create_add_on_incoming_edge (slsr_cand_t c, tree basis_name,
 -                           double_int increment, edge e, location_t loc,
 +                           widest_int increment, edge e, location_t loc,
                             bool known_stride)
  {
    basic_block insert_bb;
    /* If the add candidate along this incoming edge has the same
       index as C's hidden basis, the hidden basis represents this
       edge correctly.  */
 -  if (increment.is_zero ())
 +  if (increment == 0)
      return basis_name;
  
    basis_type = TREE_TYPE (basis_name);
      {
        tree bump_tree;
        enum tree_code code = PLUS_EXPR;
 -      double_int bump = increment * tree_to_double_int (c->stride);
 -      if (bump.is_negative ())
 +      widest_int bump = increment * wi::to_widest (c->stride);
 +      if (wi::neg_p (bump))
        {
          code = MINUS_EXPR;
          bump = -bump;
        }
  
 -      bump_tree = double_int_to_tree (basis_type, bump);
 +      bump_tree = wide_int_to_tree (basis_type, bump);
        new_stmt = gimple_build_assign_with_ops (code, lhs, basis_name,
                                               bump_tree);
      }
    else
      {
        int i;
 -      bool negate_incr = (!address_arithmetic_p && increment.is_negative ());
 +      bool negate_incr = (!address_arithmetic_p && wi::neg_p (increment));
        i = incr_vec_index (negate_incr ? -increment : increment);
        gcc_assert (i >= 0);
  
          new_stmt = gimple_build_assign_with_ops (code, lhs, basis_name,
                                                   incr_vec[i].initializer);
        }
 -      else if (increment.is_one ())
 +      else if (increment == 1)
        new_stmt = gimple_build_assign_with_ops (PLUS_EXPR, lhs, basis_name,
                                                 c->stride);
 -      else if (increment.is_minus_one ())
 +      else if (increment == -1)
        new_stmt = gimple_build_assign_with_ops (MINUS_EXPR, lhs, basis_name,
                                                 c->stride);
        else
@@@ -2163,11 -2174,11 +2167,11 @@@ create_phi_basis (slsr_cand_t c, gimpl
        /* If the phi argument is the base name of the CAND_PHI, then
         this incoming arc should use the hidden basis.  */
        if (operand_equal_p (arg, phi_cand->base_expr, 0))
 -      if (basis->index.is_zero ())
 +      if (basis->index == 0)
          feeding_def = gimple_assign_lhs (basis->cand_stmt);
        else
          {
 -          double_int incr = -basis->index;
 +          widest_int incr = -basis->index;
            feeding_def = create_add_on_incoming_edge (c, basis_name, incr,
                                                       e, loc, known_stride);
          }
          else
            {
              slsr_cand_t arg_cand = base_cand_from_table (arg);
 -            double_int diff = arg_cand->index - basis->index;
 +            widest_int diff = arg_cand->index - basis->index;
              feeding_def = create_add_on_incoming_edge (c, basis_name, diff,
                                                         e, loc, known_stride);
            }
@@@ -2230,6 -2241,7 +2234,6 @@@ replace_conditional_candidate (slsr_can
    tree basis_name, name;
    slsr_cand_t basis;
    location_t loc;
 -  double_int stride, bump;
  
    /* Look up the LHS SSA name from C's basis.  This will be the 
       RHS1 of the adds we will introduce to create new phi arguments.  */
    name = create_phi_basis (c, lookup_cand (c->def_phi)->cand_stmt,
                           basis_name, loc, KNOWN_STRIDE);
    /* Replace C with an add of the new basis phi and a constant.  */
 -  stride = tree_to_double_int (c->stride);
 -  bump = c->index * stride;
 +  widest_int bump = c->index * wi::to_widest (c->stride);
  
    replace_mult_candidate (c, name, bump);
  }
@@@ -2374,14 -2387,14 +2378,14 @@@ count_candidates (slsr_cand_t c
     candidates with the same increment, also record T_0 for subsequent use.  */
  
  static void
 -record_increment (slsr_cand_t c, double_int increment, bool is_phi_adjust)
 +record_increment (slsr_cand_t c, widest_int increment, bool is_phi_adjust)
  {
    bool found = false;
    unsigned i;
  
    /* Treat increments that differ only in sign as identical so as to
       share initializers, unless we are generating pointer arithmetic.  */
 -  if (!address_arithmetic_p && increment.is_negative ())
 +  if (!address_arithmetic_p && wi::neg_p (increment))
      increment = -increment;
  
    for (i = 0; i < incr_vec_len; i++)
        if (c->kind == CAND_ADD
          && !is_phi_adjust
          && c->index == increment
 -        && (increment.sgt (double_int_one)
 -            || increment.slt (double_int_minus_one))
 +        && (wi::gts_p (increment, 1)
 +            || wi::lts_p (increment, -1))
          && (gimple_assign_rhs_code (c->cand_stmt) == PLUS_EXPR
              || gimple_assign_rhs_code (c->cand_stmt) == POINTER_PLUS_EXPR))
        {
@@@ -2484,7 -2497,7 +2488,7 @@@ record_phi_increments (slsr_cand_t basi
          else
            {
              slsr_cand_t arg_cand = base_cand_from_table (arg);
 -            double_int diff = arg_cand->index - basis->index;
 +            widest_int diff = arg_cand->index - basis->index;
              record_increment (arg_cand, diff, PHI_ADJUST);
            }
        }
@@@ -2535,7 -2548,7 +2539,7 @@@ record_increments (slsr_cand_t c
     uses.  */
  
  static int
 -phi_incr_cost (slsr_cand_t c, double_int incr, gimple phi, int *savings)
 +phi_incr_cost (slsr_cand_t c, const widest_int &incr, gimple phi, int *savings)
  {
    unsigned i;
    int cost = 0;
          else
            {
              slsr_cand_t arg_cand = base_cand_from_table (arg);
 -            double_int diff = arg_cand->index - basis->index;
 +            widest_int diff = arg_cand->index - basis->index;
  
              if (incr == diff)
                {
@@@ -2625,10 -2638,10 +2629,10 @@@ optimize_cands_for_speed_p (slsr_cand_
  
  static int
  lowest_cost_path (int cost_in, int repl_savings, slsr_cand_t c,
 -                double_int incr, bool count_phis)
 +                const widest_int &incr, bool count_phis)
  {
    int local_cost, sib_cost, savings = 0;
 -  double_int cand_incr = cand_abs_increment (c);
 +  widest_int cand_incr = cand_abs_increment (c);
  
    if (cand_already_replaced (c))
      local_cost = cost_in;
     would go dead.  */
  
  static int
 -total_savings (int repl_savings, slsr_cand_t c, double_int incr,
 +total_savings (int repl_savings, slsr_cand_t c, const widest_int &incr,
               bool count_phis)
  {
    int savings = 0;
 -  double_int cand_incr = cand_abs_increment (c);
 +  widest_int cand_incr = cand_abs_increment (c);
  
    if (incr == cand_incr && !cand_already_replaced (c))
      savings += repl_savings + c->dead_savings;
@@@ -2725,7 -2738,7 +2729,7 @@@ analyze_increments (slsr_cand_t first_d
        /* If somehow this increment is bigger than a HWI, we won't
         be optimizing candidates that use it.  And if the increment
         has a count of zero, nothing will be done with it.  */
 -      if (!incr_vec[i].incr.fits_shwi () || !incr_vec[i].count)
 +      if (!wi::fits_shwi_p (incr_vec[i].incr) || !incr_vec[i].count)
        incr_vec[i].cost = COST_INFINITE;
  
        /* Increments of 0, 1, and -1 are always profitable to replace,
@@@ -2879,7 -2892,7 +2883,7 @@@ ncd_for_two_cands (basic_block bb1, bas
     candidates, return the earliest candidate in the block in *WHERE.  */
  
  static basic_block
 -ncd_with_phi (slsr_cand_t c, double_int incr, gimple phi,
 +ncd_with_phi (slsr_cand_t c, const widest_int &incr, gimple phi,
              basic_block ncd, slsr_cand_t *where)
  {
    unsigned i;
          else 
            {
              slsr_cand_t arg_cand = base_cand_from_table (arg);
 -            double_int diff = arg_cand->index - basis->index;
 +            widest_int diff = arg_cand->index - basis->index;
  
              if ((incr == diff) || (!address_arithmetic_p && incr == -diff))
                ncd = ncd_for_two_cands (ncd, gimple_bb (arg_cand->cand_stmt),
     return the earliest candidate in the block in *WHERE.  */
  
  static basic_block
 -ncd_of_cand_and_phis (slsr_cand_t c, double_int incr, slsr_cand_t *where)
 +ncd_of_cand_and_phis (slsr_cand_t c, const widest_int &incr, slsr_cand_t *where)
  {
    basic_block ncd = NULL;
  
     *WHERE.  */
  
  static basic_block
 -nearest_common_dominator_for_cands (slsr_cand_t c, double_int incr,
 +nearest_common_dominator_for_cands (slsr_cand_t c, const widest_int &incr,
                                    slsr_cand_t *where)
  {
    basic_block sib_ncd = NULL, dep_ncd = NULL, this_ncd = NULL, ncd;
@@@ -3019,13 -3032,13 +3023,13 @@@ insert_initializers (slsr_cand_t c
        slsr_cand_t where = NULL;
        gimple init_stmt;
        tree stride_type, new_name, incr_tree;
 -      double_int incr = incr_vec[i].incr;
 +      widest_int incr = incr_vec[i].incr;
  
        if (!profitable_increment_p (i)
 -        || incr.is_one ()
 -        || (incr.is_minus_one ()
 +        || incr == 1
 +        || (incr == -1
              && gimple_assign_rhs_code (c->cand_stmt) != POINTER_PLUS_EXPR)
 -        || incr.is_zero ())
 +        || incr == 0)
        continue;
  
        /* We may have already identified an existing initializer that
  
        /* Create the initializer and insert it in the latest possible
         dominating position.  */
 -      incr_tree = double_int_to_tree (stride_type, incr);
 +      incr_tree = wide_int_to_tree (stride_type, incr);
        init_stmt = gimple_build_assign_with_ops (MULT_EXPR, new_name,
                                                c->stride, incr_tree);
        if (where)
@@@ -3111,9 -3124,9 +3115,9 @@@ all_phi_incrs_profitable (slsr_cand_t c
            {
              int j;
              slsr_cand_t arg_cand = base_cand_from_table (arg);
 -            double_int increment = arg_cand->index - basis->index;
 +            widest_int increment = arg_cand->index - basis->index;
  
 -            if (!address_arithmetic_p && increment.is_negative ())
 +            if (!address_arithmetic_p && wi::neg_p (increment))
                increment = -increment;
  
              j = incr_vec_index (increment);
                           c->cand_num);
                  print_gimple_stmt (dump_file, phi, 0, 0);
                  fputs ("    increment: ", dump_file);
 -                dump_double_int (dump_file, increment, false);
 +                print_decs (increment, dump_file);
                  if (j < 0)
                    fprintf (dump_file,
                             "\n  Not replaced; incr_vec overflow.\n");
@@@ -3219,7 -3232,7 +3223,7 @@@ replace_one_candidate (slsr_cand_t c, u
    tree orig_rhs1, orig_rhs2;
    tree rhs2;
    enum tree_code orig_code, repl_code;
 -  double_int cand_incr;
 +  widest_int cand_incr;
  
    orig_code = gimple_assign_rhs_code (c->cand_stmt);
    orig_rhs1 = gimple_assign_rhs1 (c->cand_stmt);
       from the basis name, or an add of the stride to the basis
       name, respectively.  It may be necessary to introduce a
       cast (or reuse an existing cast).  */
 -  else if (cand_incr.is_one ())
 +  else if (cand_incr == 1)
      {
        tree stride_type = TREE_TYPE (c->stride);
        tree orig_type = TREE_TYPE (orig_rhs2);
                                              c);
      }
  
 -  else if (cand_incr.is_minus_one ())
 +  else if (cand_incr == -1)
      {
        tree stride_type = TREE_TYPE (c->stride);
        tree orig_type = TREE_TYPE (orig_rhs2);
        fputs ("  (duplicate, not actually replacing)\n", dump_file);
      }
  
 -  else if (cand_incr.is_zero ())
 +  else if (cand_incr == 0)
      {
        tree lhs = gimple_assign_lhs (c->cand_stmt);
        tree lhs_type = TREE_TYPE (lhs);
@@@ -3359,7 -3372,7 +3363,7 @@@ replace_profitable_candidates (slsr_can
  {
    if (!cand_already_replaced (c))
      {
 -      double_int increment = cand_abs_increment (c);
 +      widest_int increment = cand_abs_increment (c);
        enum tree_code orig_code = gimple_assign_rhs_code (c->cand_stmt);
        int i;
  
diff --combined gcc/gimple.c
index f6ed803857ba72126b95efa6ebfd556c1a0f3f7b,20f6010a1130bdbd47d00f8f2820ace6a1b8ee05..da7be0c4f4e8d1e3214eb699cc89401ff74aa1a5
@@@ -174,7 -174,7 +174,7 @@@ gimple_build_with_ops_stat (enum gimple
  gimple
  gimple_build_return (tree retval)
  {
-   gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 1);
+   gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 2);
    if (retval)
      gimple_return_set_retval (s, retval);
    return s;
@@@ -366,6 -366,26 +366,26 @@@ gimple_build_call_from_tree (tree t
  }
  
  
+ /* Return index of INDEX's non bound argument of the call.  */
+ unsigned
+ gimple_call_get_nobnd_arg_index (const_gimple gs, unsigned index)
+ {
+   unsigned num_args = gimple_call_num_args (gs);
+   for (unsigned n = 0; n < num_args; n++)
+     {
+       if (POINTER_BOUNDS_P (gimple_call_arg (gs, n)))
+       continue;
+       else if (index)
+       index--;
+       else
+       return n;
+     }
+   gcc_unreachable ();
+ }
  /* Extract the operands and code for expression EXPR into *SUBCODE_P,
     *OP1_P, *OP2_P and *OP3_P respectively.  */
  
@@@ -3094,16 -3114,16 +3114,16 @@@ gimple_compare_field_offset (tree f1, t
    /* Fortran and C do not always agree on what DECL_OFFSET_ALIGN
       should be, so handle differing ones specially by decomposing
       the offset into a byte and bit offset manually.  */
 -  if (host_integerp (DECL_FIELD_OFFSET (f1), 0)
 -      && host_integerp (DECL_FIELD_OFFSET (f2), 0))
 +  if (tree_fits_shwi_p (DECL_FIELD_OFFSET (f1))
 +      && tree_fits_shwi_p (DECL_FIELD_OFFSET (f2)))
      {
        unsigned HOST_WIDE_INT byte_offset1, byte_offset2;
        unsigned HOST_WIDE_INT bit_offset1, bit_offset2;
 -      bit_offset1 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f1));
 -      byte_offset1 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f1))
 +      bit_offset1 = tree_to_hwi (DECL_FIELD_BIT_OFFSET (f1));
 +      byte_offset1 = (tree_to_hwi (DECL_FIELD_OFFSET (f1))
                      + bit_offset1 / BITS_PER_UNIT);
 -      bit_offset2 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f2));
 -      byte_offset2 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f2))
 +      bit_offset2 = tree_to_hwi (DECL_FIELD_BIT_OFFSET (f2));
 +      byte_offset2 = (tree_to_hwi (DECL_FIELD_OFFSET (f2))
                      + bit_offset2 / BITS_PER_UNIT);
        if (byte_offset1 != byte_offset2)
        return false;
diff --combined gcc/gimplify.c
index 21861d244eafcf904abfb38a54a124f9c61dfd3a,0723027c392f25f579c37d5dcde276d6fcd53ea4..21dc7cad156918de572526e58f8cd98081247892
@@@ -30,8 -30,12 +30,12 @@@ along with GCC; see the file COPYING3
  #include "tree-inline.h"
  #include "tree-pretty-print.h"
  #include "langhooks.h"
- #include "tree-ssa.h"
+ #include "bitmap.h"
+ #include "gimple-ssa.h"
  #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa.h"
  #include "timevar.h"
  #include "hashtab.h"
  #include "flags.h"
  #include "vec.h"
  #include "omp-low.h"
  #include "gimple-low.h"
+ #include "cilk.h"
  
  #include "langhooks-def.h"    /* FIXME: for lhd_set_decl_assembler_name */
  #include "tree-pass.h"                /* FIXME: only for PROP_gimple_any */
- #include "tree-mudflap.h"
  #include "expr.h"
  #include "tm_p.h"
  
@@@ -710,7 -714,7 +714,7 @@@ gimple_add_tmp_var (tree tmp
    /* Later processing assumes that the object size is constant, which might
       not be true at this point.  Force the use of a constant upper bound in
       this case.  */
 -  if (!host_integerp (DECL_SIZE_UNIT (tmp), 1))
 +  if (!tree_fits_uhwi_p (DECL_SIZE_UNIT (tmp)))
      force_constant_size (tmp);
  
    DECL_CONTEXT (tmp) = current_function_decl;
@@@ -974,7 -978,7 +978,7 @@@ unshare_body (tree fndecl
  
    if (cgn)
      for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
-       unshare_body (cgn->symbol.decl);
+       unshare_body (cgn->decl);
  }
  
  /* Callback for walk_tree to unmark the visited trees rooted at *TP.
@@@ -1017,7 -1021,7 +1021,7 @@@ unvisit_body (tree fndecl
  
    if (cgn)
      for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
-       unvisit_body (cgn->symbol.decl);
+       unvisit_body (cgn->decl);
  }
  
  /* Unconditionally make an unshared copy of EXPR.  This is used when using
@@@ -1232,8 -1236,7 +1236,7 @@@ gimplify_bind_expr (tree *expr_p, gimpl
        gimple stack_restore;
  
        /* Save stack on entry and restore it on exit.  Add a try_finally
-        block to achieve this.  Note that mudflap depends on the
-        format of the emitted code: see mx_register_decls().  */
+        block to achieve this.  */
        build_stack_save_restore (&stack_save, &stack_restore);
  
        gimplify_seq_add_stmt (&cleanup, stack_restore);
@@@ -1307,6 -1310,15 +1310,15 @@@ gimplify_return_expr (tree stmt, gimple
    if (ret_expr == error_mark_node)
      return GS_ERROR;
  
+   /* Implicit _Cilk_sync must be inserted right before any return statement 
+      if there is a _Cilk_spawn in the function.  If the user has provided a 
+      _Cilk_sync, the optimizer should remove this duplicate one.  */
+   if (fn_contains_cilk_spawn_p (cfun))
+     {
+       tree impl_sync = build0 (CILK_SYNC_STMT, void_type_node);
+       gimplify_and_add (impl_sync, pre_p);
+     }
    if (!ret_expr
        || TREE_CODE (ret_expr) == RESULT_DECL
        || ret_expr == error_mark_node)
@@@ -1391,8 -1403,7 +1403,7 @@@ static voi
  gimplify_vla_decl (tree decl, gimple_seq *seq_p)
  {
    /* This is a variable-sized decl.  Simplify its size and mark it
-      for deferred expansion.  Note that mudflap depends on the format
-      of the emitted code: see mx_register_decls().  */
+      for deferred expansion.  */
    tree t, addr, ptr_type;
  
    gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
@@@ -1728,7 -1739,11 +1739,7 @@@ preprocess_case_label_vec_for_gimple (v
                  low = CASE_HIGH (labels[i - 1]);
                  if (!low)
                    low = CASE_LOW (labels[i - 1]);
 -                if ((TREE_INT_CST_LOW (low) + 1
 -                     != TREE_INT_CST_LOW (high))
 -                    || (TREE_INT_CST_HIGH (low)
 -                        + (TREE_INT_CST_LOW (high) == 0)
 -                        != TREE_INT_CST_HIGH (high)))
 +                if (wi::add (low, 1) != high)
                    break;
                }
              if (i == len)
@@@ -2127,7 -2142,6 +2138,6 @@@ gimplify_compound_lval (tree *expr_p, g
                        fallback_t fallback)
  {
    tree *p;
-   vec<tree> expr_stack;
    enum gimplify_status ret = GS_ALL_DONE, tret;
    int i;
    location_t loc = EXPR_LOCATION (*expr_p);
  
    /* Create a stack of the subexpressions so later we can walk them in
       order from inner to outer.  */
-   expr_stack.create (10);
+   stack_vec<tree, 10> expr_stack;
  
    /* We can handle anything that get_inner_reference can deal with.  */
    for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
@@@ -2493,6 -2507,12 +2503,12 @@@ gimplify_call_expr (tree *expr_p, gimpl
    if (! EXPR_HAS_LOCATION (*expr_p))
      SET_EXPR_LOCATION (*expr_p, input_location);
  
+   if (fn_contains_cilk_spawn_p (cfun)
+       && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p) 
+       && !seen_error ())
+     return (enum gimplify_status) 
+       lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, NULL);
    /* This may be a call to a builtin function.
  
       Builtin function calls may be transformed into different
@@@ -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))
        {
@@@ -4048,10 -4079,19 +4075,19 @@@ gimplify_init_constructor (tree *expr_p
           individual element initialization.  Also don't do this for small
           all-zero initializers (which aren't big enough to merit
           clearing), and don't try to make bitwise copies of
-          TREE_ADDRESSABLE types.  */
+          TREE_ADDRESSABLE types.
+          We cannot apply such transformation when compiling chkp static
+          initializer because creation of initializer image in the memory
+          will require static initialization of bounds for it.  It should
+          result in another gimplification of similar initializer and we
+          may fall into infinite loop.  */
        if (valid_const_initializer
            && !(cleared || num_nonzero_elements == 0)
-           && !TREE_ADDRESSABLE (type))
+           && !TREE_ADDRESSABLE (type)
+           && (!current_function_decl
+               || !lookup_attribute ("chkp ctor",
+                                     DECL_ATTRIBUTES (current_function_decl))))
          {
            HOST_WIDE_INT size = int_size_in_bytes (type);
            unsigned int align;
@@@ -4698,6 -4738,12 +4734,12 @@@ gimplify_modify_expr (tree *expr_p, gim
  
    gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
              || TREE_CODE (*expr_p) == INIT_EXPR);
+   
+   if (fn_contains_cilk_spawn_p (cfun)
+       && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p) 
+       && !seen_error ())
+     return (enum gimplify_status) 
+       lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, post_p);
  
    /* Trying to simplify a clobber using normal logic doesn't work,
       so handle it here.  */
@@@ -7644,6 -7690,19 +7686,19 @@@ gimplify_expr (tree *expr_p, gimple_se
            }
          break;
  
+       case CILK_SPAWN_STMT:
+         gcc_assert 
+           (fn_contains_cilk_spawn_p (cfun) 
+            && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p));
+         if (!seen_error ())
+           {
+             ret = (enum gimplify_status)
+               lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p,
+                                                        post_p);
+             break;
+           }
+         /* If errors are seen, then just process it as a CALL_EXPR.  */
        case CALL_EXPR:
          ret = gimplify_call_expr (expr_p, pre_p, fallback != fb_none);
  
          ret = gimplify_addr_expr (expr_p, pre_p, post_p);
          break;
  
+       case ANNOTATE_EXPR:
+         {
+           tree cond = TREE_OPERAND (*expr_p, 0);
+           tree id = TREE_OPERAND (*expr_p, 1);
+           tree tmp = create_tmp_var_raw (TREE_TYPE(cond), NULL);
+           gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
+           gimple call = gimple_build_call_internal (IFN_ANNOTATE, 2,
+                                                     cond, id);
+           gimple_call_set_lhs (call, tmp);
+           gimplify_seq_add_stmt (pre_p, call);
+           *expr_p = tmp;
+           ret = GS_ALL_DONE;
+           break;
+         }
        case VA_ARG_EXPR:
          ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
          break;
            break;
          }
  
+       case CILK_SYNC_STMT:
+         {
+           if (!fn_contains_cilk_spawn_p (cfun))
+             {
+               error_at (EXPR_LOCATION (*expr_p),
+                         "expected %<_Cilk_spawn%> before %<_Cilk_sync%>");
+               ret = GS_ERROR;
+             }
+           else
+             {
+               gimplify_cilk_sync (expr_p, pre_p);
+               ret = GS_ALL_DONE;
+             }
+           break;
+         }
+       
        default:
          switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
            {
@@@ -9224,118 -9314,107 +9310,107 @@@ force_gimple_operand_gsi (gimple_stmt_i
                                     var, before, m);
  }
  
- #ifndef PAD_VARARGS_DOWN
- #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
- #endif
+ /* Return a dummy expression of type TYPE in order to keep going after an
+    error.  */
  
- /* Build an indirect-ref expression over the given TREE, which represents a
-    piece of a va_arg() expansion.  */
- tree
- build_va_arg_indirect_ref (tree addr)
+ static tree
+ dummy_object (tree type)
  {
-   addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr);
-   if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF.  */
-     mf_mark (addr);
-   return addr;
+   tree t = build_int_cst (build_pointer_type (type), 0);
+   return build2 (MEM_REF, type, t, t);
  }
  
- /* The "standard" implementation of va_arg: read the value from the
-    current (padded) address and increment by the (padded) size.  */
+ /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
+    builtin function, but a very special sort of operator.  */
  
- tree
- std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
-                         gimple_seq *post_p)
- {
-   tree addr, t, type_size, rounded_size, valist_tmp;
-   unsigned HOST_WIDE_INT align, boundary;
-   bool indirect;
- #ifdef ARGS_GROW_DOWNWARD
-   /* All of the alignment and movement below is for args-grow-up machines.
-      As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
-      implement their own specialized gimplify_va_arg_expr routines.  */
-   gcc_unreachable ();
- #endif
-   indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
-   if (indirect)
-     type = build_pointer_type (type);
+ enum gimplify_status
+ gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
+ {
+   tree promoted_type, have_va_type;
+   tree valist = TREE_OPERAND (*expr_p, 0);
+   tree type = TREE_TYPE (*expr_p);
+   tree t;
+   location_t loc = EXPR_LOCATION (*expr_p);
  
-   align = PARM_BOUNDARY / BITS_PER_UNIT;
-   boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
+   /* Verify that valist is of the proper type.  */
+   have_va_type = TREE_TYPE (valist);
+   if (have_va_type == error_mark_node)
+     return GS_ERROR;
+   have_va_type = targetm.canonical_va_list_type (have_va_type);
  
-   /* When we align parameter on stack for caller, if the parameter
-      alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
-      aligned at MAX_SUPPORTED_STACK_ALIGNMENT.  We will match callee
-      here with caller.  */
-   if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
-     boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
+   if (have_va_type == NULL_TREE)
+     {
+       error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
+       return GS_ERROR;
+     }
  
-   boundary /= BITS_PER_UNIT;
+   /* Generate a diagnostic for requesting data of a type that cannot
+      be passed through `...' due to type promotion at the call site.  */
+   if ((promoted_type = lang_hooks.types.type_promotes_to (type))
+          != type)
+     {
+       static bool gave_help;
+       bool warned;
  
-   /* Hoist the valist value into a temporary for the moment.  */
-   valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
+       /* Unfortunately, this is merely undefined, rather than a constraint
+        violation, so we cannot make this an error.  If this call is never
+        executed, the program is still strictly conforming.  */
+       warned = warning_at (loc, 0,
+                          "%qT is promoted to %qT when passed through %<...%>",
+                          type, promoted_type);
+       if (!gave_help && warned)
+       {
+         gave_help = true;
+         inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
+                 promoted_type, type);
+       }
  
-   /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
-      requires greater alignment, we must perform dynamic alignment.  */
-   if (boundary > align
-       && !integer_zerop (TYPE_SIZE (type)))
-     {
-       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
-                 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
+       /* We can, however, treat "undefined" any way we please.
+        Call abort to encourage the user to fix the program.  */
+       if (warned)
+       inform (loc, "if this code is reached, the program will abort");
+       /* Before the abort, allow the evaluation of the va_list
+        expression to exit or longjmp.  */
+       gimplify_and_add (valist, pre_p);
+       t = build_call_expr_loc (loc,
+                              builtin_decl_implicit (BUILT_IN_TRAP), 0);
        gimplify_and_add (t, pre_p);
  
-       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
-                 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
-                              valist_tmp,
-                              build_int_cst (TREE_TYPE (valist), -boundary)));
-       gimplify_and_add (t, pre_p);
+       /* This is dead code, but go ahead and finish so that the
+        mode of the result comes out right.  */
+       *expr_p = dummy_object (type);
+       return GS_ALL_DONE;
      }
    else
-     boundary = align;
-   /* If the actual alignment is less than the alignment of the type,
-      adjust the type accordingly so that we don't assume strict alignment
-      when dereferencing the pointer.  */
-   boundary *= BITS_PER_UNIT;
-   if (boundary < TYPE_ALIGN (type))
      {
-       type = build_variant_type_copy (type);
-       TYPE_ALIGN (type) = boundary;
-     }
+       /* Make it easier for the backends by protecting the valist argument
+        from multiple evaluations.  */
+       if (TREE_CODE (have_va_type) == ARRAY_TYPE)
+       {
+         /* For this case, the backends will be expecting a pointer to
+            TREE_TYPE (abi), but it's possible we've
+            actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
+            So fix it.  */
+         if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
+           {
+             tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
+             valist = fold_convert_loc (loc, p1,
+                                        build_fold_addr_expr_loc (loc, valist));
+           }
  
-   /* Compute the rounded size of the type.  */
-   type_size = size_in_bytes (type);
-   rounded_size = round_up (type_size, align);
+         gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
+       }
+       else
+       gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
  
-   /* Reduce rounded_size so it's sharable with the postqueue.  */
-   gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
+       if (!targetm.gimplify_va_arg_expr)
+       /* FIXME: Once most targets are converted we should merely
+          assert this is non-null.  */
+       return GS_ALL_DONE;
  
-   /* Get AP.  */
-   addr = valist_tmp;
-   if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
-     {
-       /* Small args are padded downward.  */
-       t = fold_build2_loc (input_location, GT_EXPR, sizetype,
-                      rounded_size, size_int (align));
-       t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
-                      size_binop (MINUS_EXPR, rounded_size, type_size));
-       addr = fold_build_pointer_plus (addr, t);
+       *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
+       return GS_OK;
      }
-   /* Compute new value for AP.  */
-   t = fold_build_pointer_plus (valist_tmp, rounded_size);
-   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
-   gimplify_and_add (t, pre_p);
-   addr = fold_convert (build_pointer_type (type), addr);
-   if (indirect)
-     addr = build_va_arg_indirect_ref (addr);
-   return build_va_arg_indirect_ref (addr);
  }
  
  #include "gt-gimplify.h"
index 45220b640b2cada3a08e99ebf18e8fc08129ce73,c4d326861786fc08b5c3c355d0ee7aea6d0b523f..9dbbfbf8f1da8b37fa6e94aaefa5dd5d654a2ba5
@@@ -3342,23 -3342,19 +3342,19 @@@ Type_conversion_expression::do_get_tree
        tree int_type_tree = type_to_tree(int_type->get_backend(gogo));
  
        expr_tree = fold_convert(int_type_tree, expr_tree);
 -      if (host_integerp(expr_tree, 0))
 +      if (tree_fits_shwi_p(expr_tree))
        {
 -        HOST_WIDE_INT intval = tree_low_cst(expr_tree, 0);
 +        HOST_WIDE_INT intval = tree_to_shwi(expr_tree);
          std::string s;
          Lex::append_char(intval, true, &s, this->location());
          Expression* se = Expression::make_string(s, this->location());
          return se->get_tree(context);
        }
  
-       static tree int_to_string_fndecl;
-       ret = Gogo::call_builtin(&int_to_string_fndecl,
-                              this->location(),
-                              "__go_int_to_string",
-                              1,
-                              type_tree,
-                              int_type_tree,
-                              expr_tree);
+       Call_expression* i2s_expr =
+           Runtime::make_call(Runtime::INT_TO_STRING, this->location(), 1,
+                              this->expr_);
+       ret = i2s_expr->get_tree(context);
      }
    else if (type->is_string_type() && expr_type->is_slice_type())
      {
      {
        Type* e = type->array_type()->element_type()->forwarded();
        go_assert(e->integer_type() != NULL);
+       Call_expression* s2a_expr;
        if (e->integer_type()->is_byte())
-       {
-         tree string_to_byte_array_fndecl = NULL_TREE;
-         ret = Gogo::call_builtin(&string_to_byte_array_fndecl,
-                                  this->location(),
-                                  "__go_string_to_byte_array",
-                                  1,
-                                  type_tree,
-                                  TREE_TYPE(expr_tree),
-                                  expr_tree);
-       }
+         s2a_expr = Runtime::make_call(Runtime::STRING_TO_BYTE_ARRAY,
+                                       this->location(), 1, this->expr_);
        else
        {
          go_assert(e->integer_type()->is_rune());
-         tree string_to_int_array_fndecl = NULL_TREE;
-         ret = Gogo::call_builtin(&string_to_int_array_fndecl,
-                                  this->location(),
-                                  "__go_string_to_int_array",
-                                  1,
-                                  type_tree,
-                                  TREE_TYPE(expr_tree),
-                                  expr_tree);
+           s2a_expr = Runtime::make_call(Runtime::STRING_TO_INT_ARRAY,
+                                         this->location(), 1, this->expr_);
        }
+       ret = s2a_expr->get_tree(context);
      }
    else if ((type->is_unsafe_pointer_type()
            && expr_type->points_to() != NULL)
@@@ -10250,7 -10235,9 +10235,9 @@@ Index_expression::do_traverse(Traverse
    if (Expression::traverse(&this->left_, traverse) == TRAVERSE_EXIT
        || Expression::traverse(&this->start_, traverse) == TRAVERSE_EXIT
        || (this->end_ != NULL
-         && Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT))
+         && Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT)
+       || (this->cap_ != NULL
+           && Expression::traverse(&this->cap_, traverse) == TRAVERSE_EXIT))
      return TRAVERSE_EXIT;
    return TRAVERSE_CONTINUE;
  }
@@@ -10265,6 -10252,7 +10252,7 @@@ Index_expression::do_lower(Gogo*, Named
    Expression* left = this->left_;
    Expression* start = this->start_;
    Expression* end = this->end_;
+   Expression* cap = this->cap_;
  
    Type* type = left->type();
    if (type->is_error())
        return Expression::make_error(location);
      }
    else if (type->array_type() != NULL)
-     return Expression::make_array_index(left, start, end, location);
+     return Expression::make_array_index(left, start, end, cap, location);
    else if (type->points_to() != NULL
           && type->points_to()->array_type() != NULL
           && !type->points_to()->is_slice_type())
      {
        Expression* deref = Expression::make_unary(OPERATOR_MULT, left,
                                                 location);
-       return Expression::make_array_index(deref, start, end, location);
+       return Expression::make_array_index(deref, start, end, cap, location);
      }
    else if (type->is_string_type())
-     return Expression::make_string_index(left, start, end, location);
+     {
+       if (cap != NULL)
+         {
+           error_at(location, "invalid 3-index slice of string");
+           return Expression::make_error(location);
+         }
+       return Expression::make_string_index(left, start, end, location);
+     }
    else if (type->map_type() != NULL)
      {
-       if (end != NULL)
+       if (end != NULL || cap != NULL)
        {
          error_at(location, "invalid slice of map");
          return Expression::make_error(location);
      }
  }
  
- // Write an indexed expression (expr[expr:expr] or expr[expr]) to a
- // dump context
+ // Write an indexed expression
+ // (expr[expr:expr:expr], expr[expr:expr] or expr[expr]) to a dump context.
  
  void
  Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context, 
                                        const Expression* expr, 
                                        const Expression* start,
-                                       const Expression* end)
+                                       const Expression* end,
+                                       const Expression* cap)
  {
    expr->dump_expression(ast_dump_context);
    ast_dump_context->ostream() << "[";
        ast_dump_context->ostream() << ":";
        end->dump_expression(ast_dump_context);
      }
+   if (cap != NULL)
+     {
+       ast_dump_context->ostream() << ":";
+       cap->dump_expression(ast_dump_context);
+     }
    ast_dump_context->ostream() << "]";
  }
  
@@@ -10334,16 -10335,16 +10335,16 @@@ Index_expression::do_dump_expression(As
      const
  {
    Index_expression::dump_index_expression(ast_dump_context, this->left_, 
-                                           this->start_, this->end_);
+                                           this->start_, this->end_, this->cap_);
  }
  
  // Make an index expression.
  
  Expression*
  Expression::make_index(Expression* left, Expression* start, Expression* end,
-                      Location location)
+                      Expression* cap, Location location)
  {
-   return new Index_expression(left, start, end, location);
+   return new Index_expression(left, start, end, cap, location);
  }
  
  // An array index.  This is used for both indexing and slicing.
@@@ -10352,9 -10353,9 +10353,9 @@@ class Array_index_expression : public E
  {
   public:
    Array_index_expression(Expression* array, Expression* start,
-                        Expression* end, Location location)
+                        Expression* end, Expression* cap, Location location)
      : Expression(EXPRESSION_ARRAY_INDEX, location),
-       array_(array), start_(start), end_(end), type_(NULL)
+       array_(array), start_(start), end_(end), cap_(cap), type_(NULL)
    { }
  
   protected:
                                        (this->end_ == NULL
                                         ? NULL
                                         : this->end_->copy()),
+                                       (this->cap_ == NULL
+                                        ? NULL
+                                        : this->cap_->copy()),
                                        this->location());
    }
  
    // The end index of a slice.  This may be NULL for a simple array
    // index, or it may be a nil expression for the length of the array.
    Expression* end_;
+   // The capacity argument of a slice.  This may be NULL for an array index or
+   // slice.
+   Expression* cap_;
    // The type of the expression.
    Type* type_;
  };
@@@ -10427,6 -10434,11 +10434,11 @@@ Array_index_expression::do_traverse(Tra
        if (Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT)
        return TRAVERSE_EXIT;
      }
+   if (this->cap_ != NULL)
+     {
+       if (Expression::traverse(&this->cap_, traverse) == TRAVERSE_EXIT)
+         return TRAVERSE_EXIT;
+     }
    return TRAVERSE_CONTINUE;
  }
  
@@@ -10466,6 -10478,8 +10478,8 @@@ Array_index_expression::do_determine_ty
    this->start_->determine_type_no_context();
    if (this->end_ != NULL)
      this->end_->determine_type_no_context();
+   if (this->cap_ != NULL)
+     this->cap_->determine_type_no_context();
  }
  
  // Check types of an array index.
@@@ -10488,6 -10502,14 +10502,14 @@@ Array_index_expression::do_check_types(
        && (!this->end_->numeric_constant_value(&nc)
          || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
      this->report_error(_("slice end must be integer"));
+   if (this->cap_ != NULL
+       && this->cap_->type()->integer_type() == NULL
+       && !this->cap_->type()->is_error()
+       && !this->cap_->is_nil_expression()
+       && !this->cap_->is_error_expression()
+       && (!this->cap_->numeric_constant_value(&nc)
+         || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
+     this->report_error(_("slice capacity must be integer"));
  
    Array_type* array_type = this->array_->type()->array_type();
    if (array_type == NULL)
      {
        Numeric_constant enc;
        mpz_t eval;
+       bool eval_valid = false;
        if (this->end_->numeric_constant_value(&enc) && enc.to_int(&eval))
        {
+         eval_valid = true;
          if (mpz_sgn(eval) < 0
              || mpz_sizeinbase(eval, 2) >= int_bits
              || (lval_valid && mpz_cmp(eval, lval) > 0))
            }
          else if (ival_valid && mpz_cmp(ival, eval) > 0)
            this->report_error(_("inverted slice range"));
-         mpz_clear(eval);
        }
+       Numeric_constant cnc;
+       mpz_t cval;
+       if (this->cap_ != NULL
+           && this->cap_->numeric_constant_value(&cnc) && cnc.to_int(&cval))
+         {
+           if (mpz_sgn(cval) < 0
+               || mpz_sizeinbase(cval, 2) >= int_bits
+               || (lval_valid && mpz_cmp(cval, lval) > 0))
+             {
+               error_at(this->cap_->location(), "array index out of bounds");
+               this->set_is_error();
+             }
+         else if (ival_valid && mpz_cmp(ival, cval) > 0)
+           {
+             error_at(this->cap_->location(),
+                      "invalid slice index: capacity less than start");
+             this->set_is_error();
+           }
+           else if (eval_valid && mpz_cmp(eval, cval) > 0)
+             {
+               error_at(this->cap_->location(),
+                        "invalid slice index: capacity less than length");
+               this->set_is_error();
+             }
+           mpz_clear(cval);
+         }
+       if (eval_valid)
+         mpz_clear(eval);
      }
    if (ival_valid)
      mpz_clear(ival);
@@@ -10617,9 -10670,17 +10670,17 @@@ Array_index_expression::do_get_tree(Tra
        capacity_tree = save_expr(capacity_tree);
      }
  
+   tree cap_arg = capacity_tree;
+   if (this->cap_ != NULL)
+     {
+       cap_arg = this->cap_->get_tree(context);
+       if (cap_arg == error_mark_node)
+         return error_mark_node;
+     }
    tree length_type = (length_tree != NULL_TREE
                      ? TREE_TYPE(length_tree)
-                     : TREE_TYPE(capacity_tree));
+                     : TREE_TYPE(cap_arg));
  
    tree bad_index = boolean_false_node;
  
  
    // Array slice.
  
+   if (this->cap_ != NULL)
+     {
+       if (!DECL_P(cap_arg))
+         cap_arg = save_expr(cap_arg);
+       if (!INTEGRAL_TYPE_P(TREE_TYPE(cap_arg)))
+         cap_arg = convert_to_integer(length_type, cap_arg);
+       bad_index = Expression::check_bounds(cap_arg, length_type, bad_index,
+                                            loc);
+       cap_arg = fold_convert_loc(loc.gcc_location(), length_type, cap_arg);
+       tree bad_cap = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
+                                      boolean_type_node,
+                                      fold_build2_loc(loc.gcc_location(),
+                                                      LT_EXPR, boolean_type_node,
+                                                      cap_arg, start_tree),
+                                      fold_build2_loc(loc.gcc_location(),
+                                                      GT_EXPR, boolean_type_node,
+                                                      cap_arg, capacity_tree));
+       bad_index = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
+                                   boolean_type_node, bad_index, bad_cap);
+     }
    tree end_tree;
    if (this->end_->is_nil_expression())
      end_tree = length_tree;
                                                     end_tree, start_tree),
                                     fold_build2_loc(loc.gcc_location(),
                                                       GT_EXPR, boolean_type_node,
-                                                    end_tree, capacity_tree));
+                                                    end_tree, cap_arg));
        bad_index = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
                                    boolean_type_node, bad_index, bad_end);
      }
  
    Type* element_type = array_type->element_type();
    tree element_type_tree = type_to_tree(element_type->get_backend(gogo));
    if (element_type_tree == error_mark_node)
                                              length_type, end_tree, start_tree);
  
    tree result_capacity_tree = fold_build2_loc(loc.gcc_location(), MINUS_EXPR,
-                                               length_type, capacity_tree,
-                                               start_tree);
+                                               length_type, cap_arg, start_tree);
  
    tree struct_tree = type_to_tree(this->type()->get_backend(gogo));
    go_assert(TREE_CODE(struct_tree) == RECORD_TYPE);
@@@ -10795,16 -10879,17 +10879,17 @@@ Array_index_expression::do_dump_express
      const
  {
    Index_expression::dump_index_expression(ast_dump_context, this->array_, 
-                                           this->start_, this->end_);
+                                           this->start_, this->end_, this->cap_);
  }
  
- // Make an array index expression.  END may be NULL.
+ // Make an array index expression.  END and CAP may be NULL.
  
  Expression*
  Expression::make_array_index(Expression* array, Expression* start,
-                            Expression* end, Location location)
+                              Expression* end, Expression* cap,
+                              Location location)
  {
-   return new Array_index_expression(array, start, end, location);
+   return new Array_index_expression(array, start, end, cap, location);
  }
  
  // A string index.  This is used for both indexing and slicing.
  String_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
      const
  {
-   Index_expression::dump_index_expression(ast_dump_context, this->string_, 
-                                         this->start_, this->end_);
+   Index_expression::dump_index_expression(ast_dump_context, this->string_,
+                                           this->start_, this->end_, NULL);
  }
  
  // Make a string index expression.  END may be NULL.
  Map_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) 
      const
  {
-   Index_expression::dump_index_expression(ast_dump_context, 
-                                           this->map_, this->index_, NULL);
+   Index_expression::dump_index_expression(ast_dump_context, this->map_,
+                                           this->index_, NULL, NULL);
  }
  
  // Make a map index expression.
index 883011c8532b8e1250fc50256f51e13ed56515b4,ec4c1d1f461fc1480ae545f0429174577943c8b1..ce3c5bd0792ca73d68555873329ae1cbfee951a6
@@@ -35,7 -35,12 +35,12 @@@ along with GCC; see the file COPYING3
  #include "system.h"
  #include "coretypes.h"
  #include "diagnostic-core.h"
- #include "tree-ssa.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-into-ssa.h"
  #include "tree-pass.h"
  #include "cfgloop.h"
  #include "tree-chrec.h"
@@@ -63,13 -68,14 +68,13 @@@ gmp_cst_to_tree (tree type, mpz_t val
  {
    tree t = type ? type : integer_type_node;
    mpz_t tmp;
 -  double_int di;
  
    mpz_init (tmp);
    mpz_set (tmp, val);
 -  di = mpz_get_double_int (t, tmp, true);
 +  wide_int wi = wi::from_mpz (t, tmp, true);
    mpz_clear (tmp);
  
 -  return double_int_to_tree (t, di);
 +  return wide_int_to_tree (t, wi);
  }
  
  /* Sets RES to the min of V1 and V2.  */
@@@ -1646,8 -1652,7 +1651,7 @@@ debug_generated_program (scop_p scop
  bool
  gloog (scop_p scop, bb_pbb_htab_type bb_pbb_mapping)
  {
-   vec<tree> newivs;
-   newivs.create (10);
+   stack_vec<tree, 10> newivs;
    loop_p context_loop;
    sese region = SCOP_REGION (scop);
    ifsese if_region = NULL;
  
    newivs_index.dispose ();
    params_index.dispose ();
-   newivs.release ();
    cloog_clast_free (clast);
    timevar_pop (TV_GRAPHITE_CODE_GEN);
  
index e56aa871773bfccce94a36bcc339b71151972a7a,e73a349803a823ea1c1596a1ded8854884f834b2..f1dd455fb05cca4c3b082c632afa54fa784c4882
@@@ -31,6 -31,15 +31,15 @@@ along with GCC; see the file COPYING3
  
  #include "system.h"
  #include "coretypes.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-into-ssa.h"
  #include "tree-ssa.h"
  #include "cfgloop.h"
  #include "tree-chrec.h"
@@@ -160,10 -169,10 +169,10 @@@ graphite_can_represent_init (tree e
      case MULT_EXPR:
        if (chrec_contains_symbols (TREE_OPERAND (e, 0)))
        return graphite_can_represent_init (TREE_OPERAND (e, 0))
 -        && host_integerp (TREE_OPERAND (e, 1), 0);
 +        && tree_fits_shwi_p (TREE_OPERAND (e, 1));
        else
        return graphite_can_represent_init (TREE_OPERAND (e, 1))
 -        && host_integerp (TREE_OPERAND (e, 0), 0);
 +        && tree_fits_shwi_p (TREE_OPERAND (e, 0));
  
      case PLUS_EXPR:
      case POINTER_PLUS_EXPR:
@@@ -466,8 -475,7 +475,7 @@@ scopdet_basic_block_info (basic_block b
  
      case GBB_LOOP_SING_EXIT_HEADER:
        {
-       vec<sd_region> regions;
-       regions.create (3);
+       stack_vec<sd_region, 3> regions;
        struct scopdet_info sinfo;
        edge exit_e = single_exit (loop);
  
        {
          /* XXX: For now we just do not join loops with multiple exits.  If the
             exits lead to the same bb it may be possible to join the loop.  */
-         vec<sd_region> regions;
-       regions.create (3);
+         stack_vec<sd_region, 3> regions;
          vec<edge> exits = get_loop_exit_edges (loop);
          edge e;
          int i;
        }
      case GBB_COND_HEADER:
        {
-       vec<sd_region> regions;
-       regions.create (3);
+       stack_vec<sd_region, 3> regions;
        struct scopdet_info sinfo;
        vec<basic_block> dominated;
        int i;
@@@ -1180,8 -1186,7 +1186,7 @@@ print_graphite_statistics (FILE* file, 
  static void
  limit_scops (vec<scop_p> *scops)
  {
-   vec<sd_region> regions;
-   regions.create (3);
+   stack_vec<sd_region, 3> regions;
  
    int i;
    scop_p scop;
  
    create_sese_edges (regions);
    build_graphite_scops (regions, scops);
-   regions.release ();
  }
  
  /* Returns true when P1 and P2 are close phis with the same
@@@ -1395,8 -1399,7 +1399,7 @@@ voi
  build_scops (vec<scop_p> *scops)
  {
    struct loop *loop = current_loops->tree_root;
-   vec<sd_region> regions;
-   regions.create (3);
+   stack_vec<sd_region, 3> regions;
  
    canonicalize_loop_closed_ssa_form ();
    build_scops_1 (single_succ (ENTRY_BLOCK_PTR), ENTRY_BLOCK_PTR->loop_father,
@@@ -1586,7 -1589,7 +1589,7 @@@ dot_all_scops (vec<scop_p> scops
  DEBUG_FUNCTION void
  dot_scop (scop_p scop)
  {
-   vec<scop_p> scops = vNULL;
+   stack_vec<scop_p, 1> scops;
  
    if (scop)
      scops.safe_push (scop);
  #else
    dot_all_scops_1 (stderr, scops);
  #endif
-   scops.release ();
  }
  
  #endif
index b929511c728f85d5023e3f23a96c776e5d474e1f,6c2ac41b30e74952ede2c4fb3c264ae4266f5312..5a1f1bf89509aa20e96ca268323a198c23e0ee72
@@@ -33,7 -33,17 +33,17 @@@ along with GCC; see the file COPYING3
  
  #include "system.h"
  #include "coretypes.h"
- #include "tree-ssa.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-into-ssa.h"
  #include "tree-pass.h"
  #include "cfgloop.h"
  #include "tree-chrec.h"
@@@ -53,7 -63,8 +63,7 @@@
  static inline void
  tree_int_to_gmp (tree t, mpz_t res)
  {
 -  double_int di = tree_to_double_int (t);
 -  mpz_set_double_int (res, di, TYPE_UNSIGNED (TREE_TYPE (t)));
 +  wi::to_mpz (t, res, TYPE_SIGN (TREE_TYPE (t)));
  }
  
  /* Returns the index of the PHI argument defined in the outermost
@@@ -1005,7 -1016,7 +1015,7 @@@ build_loop_iteration_domains (scop_p sc
    /* loop_i <= expr_nb_iters */
    else if (!chrec_contains_undetermined (nb_iters))
      {
 -      double_int nit;
 +      widest_int nit;
        isl_pw_aff *aff;
        isl_set *valid;
        isl_local_space *ls;
          isl_constraint *c;
  
          mpz_init (g);
 -        mpz_set_double_int (g, nit, false);
 +        wi::to_mpz (nit, g, SIGNED);
          mpz_sub_ui (g, g, 1);
          approx = extract_affine_gmp (g, isl_set_get_space (inner));
          x = isl_pw_aff_ge_set (approx, aff);
@@@ -1220,27 -1231,18 +1230,18 @@@ class sese_dom_walker : public dom_walk
  {
  public:
    sese_dom_walker (cdi_direction, sese);
-   ~sese_dom_walker ();
  
    virtual void before_dom_children (basic_block);
    virtual void after_dom_children (basic_block);
  
  private:
-   vec<gimple> m_conditions, m_cases;
+   stack_vec<gimple, 3> m_conditions, m_cases;
    sese m_region;
  };
  
  sese_dom_walker::sese_dom_walker (cdi_direction direction, sese region)
    : dom_walker (direction), m_region (region)
  {
-   m_conditions.create (3);
-   m_cases.create (3);
- }
- sese_dom_walker::~sese_dom_walker ()
- {
-   m_conditions.release ();
-   m_cases.release ();
  }
  
  /* Call-back for dom_walk executed before visiting the dominated
@@@ -1504,9 -1506,9 +1505,9 @@@ pdr_add_data_dimensions (isl_set *exten
           subscript - low >= 0 and high - subscript >= 0 in case one of
         the two bounds isn't known.  Do the same here?  */
  
 -      if (host_integerp (low, 0)
 +      if (tree_fits_shwi_p (low)
          && high
 -        && host_integerp (high, 0)
 +        && tree_fits_shwi_p (high)
          /* 1-element arrays at end of structures may extend over
             their declared size.  */
          && !(array_at_struct_end_p (ref)
@@@ -1879,8 -1881,7 +1880,7 @@@ build_scop_drs (scop_p scop
    int i, j;
    poly_bb_p pbb;
    data_reference_p dr;
-   vec<data_reference_p> drs;
-   drs.create (3);
+   stack_vec<data_reference_p, 3> drs;
  
    /* Remove all the PBBs that do not have data references: these basic
       blocks are not handled in the polyhedral representation.  */
@@@ -1978,8 -1979,7 +1978,7 @@@ insert_stmts (scop_p scop, gimple stmt
              gimple_stmt_iterator insert_gsi)
  {
    gimple_stmt_iterator gsi;
-   vec<gimple> x;
-   x.create (3);
+   stack_vec<gimple, 3> x;
  
    gimple_seq_add_stmt (&stmts, stmt);
    for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
  
    gsi_insert_seq_before (&insert_gsi, stmts, GSI_SAME_STMT);
    analyze_drs_in_stmts (scop, gsi_bb (insert_gsi), x);
-   x.release ();
  }
  
  /* Insert the assignment "RES := EXPR" just after AFTER_STMT.  */
@@@ -1999,8 -1998,7 +1997,7 @@@ insert_out_of_ssa_copy (scop_p scop, tr
    gimple_stmt_iterator gsi;
    tree var = force_gimple_operand (expr, &stmts, true, NULL_TREE);
    gimple stmt = gimple_build_assign (unshare_expr (res), var);
-   vec<gimple> x;
-   x.create (3);
+   stack_vec<gimple, 3> x;
  
    gimple_seq_add_stmt (&stmts, stmt);
    for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
      }
  
    analyze_drs_in_stmts (scop, gimple_bb (after_stmt), x);
-   x.release ();
  }
  
  /* Creates a poly_bb_p for basic_block BB from the existing PBB.  */
@@@ -2056,8 -2053,7 +2052,7 @@@ insert_out_of_ssa_copy_on_edge (scop_p 
    tree var = force_gimple_operand (expr, &stmts, true, NULL_TREE);
    gimple stmt = gimple_build_assign (unshare_expr (res), var);
    basic_block bb;
-   vec<gimple> x;
-   x.create (3);
+   stack_vec<gimple, 3> x;
  
    gimple_seq_add_stmt (&stmts, stmt);
    for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
      new_pbb_from_pbb (scop, pbb_from_bb (e->src), bb);
  
    analyze_drs_in_stmts (scop, bb, x);
-   x.release ();
  }
  
  /* Creates a zero dimension array of the same type as VAR.  */
@@@ -2870,8 -2865,7 +2864,7 @@@ remove_phi (gimple phi
    tree def;
    use_operand_p use_p;
    gimple_stmt_iterator gsi;
-   vec<gimple> update;
-   update.create (3);
+   stack_vec<gimple, 3> update;
    unsigned int i;
    gimple stmt;
  
    FOR_EACH_VEC_ELT (update, i, stmt)
      update_stmt (stmt);
  
-   update.release ();
    gsi = gsi_for_phi_node (phi);
    remove_phi_node (&gsi, false);
  }
@@@ -3031,18 -3023,14 +3022,14 @@@ rewrite_commutative_reductions_out_of_s
                                                     gimple close_phi)
  {
    bool res;
-   vec<gimple> in;
-   in.create (10);
-   vec<gimple> out;
-   out.create (10);
+   stack_vec<gimple, 10> in;
+   stack_vec<gimple, 10> out;
  
    detect_commutative_reduction (scop, close_phi, &in, &out);
    res = in.length () > 1;
    if (res)
      translate_scalar_reduction_to_array (scop, in, out);
  
-   in.release ();
-   out.release ();
    return res;
  }
  
diff --combined gcc/ipa-cp.c
index f6f49dadc94ae0e76f3efa28c2ef1776c67f5a5d,72a96d22c17b14ba89031fe6207a15e21b661dac..82d94057b77fa331cac51139b59cb41db9b71088
@@@ -104,11 -104,10 +104,10 @@@ along with GCC; see the file COPYING3
  #include "system.h"
  #include "coretypes.h"
  #include "tree.h"
- #include "target.h"
  #include "gimple.h"
- #include "cgraph.h"
+ #include "target.h"
  #include "ipa-prop.h"
- #include "tree-ssa.h"
+ #include "bitmap.h"
  #include "tree-pass.h"
  #include "flags.h"
  #include "diagnostic.h"
@@@ -353,7 -352,7 +352,7 @@@ print_lattice (FILE * f, struct ipcp_la
  
          fprintf (f, " [from:");
          for (s = val->sources; s; s = s->next)
-           fprintf (f, " %i(%i)", s->cs->caller->symbol.order,
+           fprintf (f, " %i(%i)", s->cs->caller->order,
                     s->cs->frequency);
          fprintf (f, "]");
        }
@@@ -383,7 -382,7 +382,7 @@@ print_all_lattices (FILE * f, bool dump
  
        info = IPA_NODE_REF (node);
        fprintf (f, "  Node: %s/%i:\n", cgraph_node_name (node),
-              node->symbol.order);
+              node->order);
        count = ipa_get_param_count (info);
        for (i = 0; i < count; i++)
        {
@@@ -424,16 -423,16 +423,16 @@@ determine_versionability (struct cgraph
    /* There are a number of generic reasons functions cannot be versioned.  We
       also cannot remove parameters if there are type attributes such as fnspec
       present.  */
-   if (node->symbol.alias || node->thunk.thunk_p)
+   if (node->alias || node->thunk.thunk_p)
      reason = "alias or thunk";
    else if (!node->local.versionable)
      reason = "not a tree_versionable_function";
    else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
      reason = "insufficient body availability";
  
-   if (reason && dump_file && !node->symbol.alias && !node->thunk.thunk_p)
+   if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
      fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
-            cgraph_node_name (node), node->symbol.order, reason);
+            cgraph_node_name (node), node->order, reason);
  
    node->local.versionable = (reason == NULL);
  }
@@@ -509,7 -508,7 +508,7 @@@ ipcp_cloning_candidate_p (struct cgraph
        return false;
      }
  
-   if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->symbol.decl)))
+   if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
      {
        if (dump_file)
          fprintf (dump_file, "Not considering %s for cloning; "
@@@ -711,9 -710,9 +710,9 @@@ initialize_node_lattices (struct cgraph
            set_all_contains_variable (plats);
        }
        if (dump_file && (dump_flags & TDF_DETAILS)
-         && !node->symbol.alias && !node->thunk.thunk_p)
+         && !node->alias && !node->thunk.thunk_p)
        fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
-                cgraph_node_name (node), node->symbol.order,
+                cgraph_node_name (node), node->order,
                 disable ? "BOTTOM" : "VARIABLE");
      }
  
@@@ -1372,7 -1371,7 +1371,7 @@@ propagate_aggs_accross_jump_function (s
          if (item->offset < 0)
            continue;
          gcc_checking_assert (is_gimple_ip_invariant (item->value));
 -        val_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (item->value)), 1);
 +        val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value)));
  
          if (merge_agg_lats_step (dest_plats, item->offset, val_size,
                                   &aglat, pre_existing, &ret))
@@@ -1406,7 -1405,7 +1405,7 @@@ propagate_constants_accross_call (struc
    int i, args_count, parms_count;
  
    callee = cgraph_function_node (cs->callee, &availability);
-   if (!callee->symbol.definition)
+   if (!callee->definition)
      return false;
    gcc_checking_assert (cgraph_function_with_gimple_body_p (callee));
    callee_info = IPA_NODE_REF (callee);
       parameter.  However, we might need to uncover a thunk from below a series
       of aliases first.  */
    alias_or_thunk = cs->callee;
-   while (alias_or_thunk->symbol.alias)
+   while (alias_or_thunk->alias)
      alias_or_thunk = cgraph_alias_target (alias_or_thunk);
    if (alias_or_thunk->thunk.thunk_p)
      {
@@@ -1598,7 -1597,7 +1597,7 @@@ devirtualization_time_bonus (struct cgr
        /* Only bare minimum benefit for clearly un-inlineable targets.  */
        res += 1;
        callee = cgraph_get_node (target);
-       if (!callee || !callee->symbol.definition)
+       if (!callee || !callee->definition)
        continue;
        isummary = inline_summary (callee);
        if (!isummary->inlinable)
        else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
        res += 15;
        else if (isummary->size <= MAX_INLINE_INSNS_AUTO
-              || DECL_DECLARED_INLINE_P (callee->symbol.decl))
+              || DECL_DECLARED_INLINE_P (callee->decl))
        res += 7;
      }
  
@@@ -1641,7 -1640,7 +1640,7 @@@ good_cloning_opportunity_p (struct cgra
  {
    if (time_benefit == 0
        || !flag_ipa_cp_clone
-       || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->symbol.decl)))
+       || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
      return false;
  
    gcc_assert (size_cost > 0);
@@@ -1818,7 -1817,7 +1817,7 @@@ estimate_local_effects (struct cgraph_n
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
-            cgraph_node_name (node), node->symbol.order, base_time);
+            cgraph_node_name (node), node->order, base_time);
  
    always_const = gather_context_independent_values (info, &known_csts,
                                                    &known_binfos, &known_aggs,
@@@ -2220,7 -2219,7 +2219,7 @@@ ipcp_propagate_stage (struct topo_info 
                                   ipa_get_param_count (info));
        initialize_node_lattices (node);
        }
-     if (node->symbol.definition && !node->symbol.alias)
+     if (node->definition && !node->alias)
        overall_size += inline_summary (node)->self_size;
      if (node->count > max_count)
        max_count = node->count;
@@@ -2288,8 -2287,8 +2287,8 @@@ ipcp_discover_new_direct_edges (struct 
                    fprintf (dump_file, "     controlled uses count of param "
                             "%i bumped down to %i\n", param_index, c);
                  if (c == 0
-                     && (to_del = ipa_find_reference ((symtab_node) node,
-                                                      (symtab_node) cs->callee,
+                     && (to_del = ipa_find_reference (node,
+                                                      cs->callee,
                                                       NULL, 0)))
                    {
                      if (dump_file && (dump_flags & TDF_DETAILS))
@@@ -2545,7 -2544,7 +2544,7 @@@ update_profiling_info (struct cgraph_no
        fprintf (dump_file, "    Problem: node %s/%i has too low count "
                 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
                 "counts is " HOST_WIDE_INT_PRINT_DEC "\n",
-                cgraph_node_name (orig_node), orig_node->symbol.order,
+                cgraph_node_name (orig_node), orig_node->order,
                 (HOST_WIDE_INT) orig_node_count,
                 (HOST_WIDE_INT) (orig_sum + new_sum));
  
@@@ -2678,13 -2677,13 +2677,13 @@@ create_specialized_node (struct cgraph_
                                          args_to_skip, "constprop");
    ipa_set_node_agg_value_chain (new_node, aggvals);
    for (av = aggvals; av; av = av->next)
-     ipa_maybe_record_reference ((symtab_node) new_node, av->value,
+     ipa_maybe_record_reference (new_node, av->value,
                                IPA_REF_ADDR, NULL);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
        fprintf (dump_file, "     the new node is %s/%i.\n",
-              cgraph_node_name (new_node), new_node->symbol.order);
+              cgraph_node_name (new_node), new_node->order);
        if (aggvals)
        ipa_dump_agg_replacement_values (dump_file, aggvals);
      }
@@@ -3237,9 -3236,9 +3236,9 @@@ perhaps_add_new_callers (struct cgraph_
                    fprintf (dump_file, " - adding an extra caller %s/%i"
                             " of %s/%i\n",
                             xstrdup (cgraph_node_name (cs->caller)),
-                            cs->caller->symbol.order,
+                            cs->caller->order,
                             xstrdup (cgraph_node_name (val->spec_node)),
-                            val->spec_node->symbol.order);
+                            val->spec_node->order);
  
                  cgraph_redirect_edge_callee (cs, val->spec_node);
                  redirected_sum += cs->count;
@@@ -3343,7 -3342,7 +3342,7 @@@ decide_about_value (struct cgraph_node 
  
    if (dump_file)
      fprintf (dump_file, "  Creating a specialized node of %s/%i.\n",
-            cgraph_node_name (node), node->symbol.order);
+            cgraph_node_name (node), node->order);
  
    callers = gather_edges_for_value (val, caller_count);
    kv = known_csts.copy ();
@@@ -3380,7 -3379,7 +3379,7 @@@ decide_whether_version_node (struct cgr
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
-            cgraph_node_name (node), node->symbol.order);
+            cgraph_node_name (node), node->order);
  
    gather_context_independent_values (info, &known_csts, &known_binfos,
                                  info->do_clone_for_all_contexts ? &known_aggs
        if (dump_file)
        fprintf (dump_file, " - Creating a specialized node of %s/%i "
                 "for all known contexts.\n", cgraph_node_name (node),
-                node->symbol.order);
+                node->order);
  
        callers = collect_callers_of_node (node);
        move_binfos_to_values (known_csts, known_binfos);
@@@ -3499,23 -3498,23 +3498,23 @@@ static voi
  identify_dead_nodes (struct cgraph_node *node)
  {
    struct cgraph_node *v;
-   for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
+   for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
      if (cgraph_will_be_removed_from_program_if_no_direct_calls (v)
        && !cgraph_for_node_and_aliases (v,
                                         has_undead_caller_from_outside_scc_p,
                                         NULL, true))
        IPA_NODE_REF (v)->node_dead = 1;
  
-   for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
+   for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
      if (!IPA_NODE_REF (v)->node_dead)
        spread_undeadness (v);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
-       for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
+       for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
        if (IPA_NODE_REF (v)->node_dead)
          fprintf (dump_file, "  Marking node as dead: %s/%i.\n",
-                  cgraph_node_name (v), v->symbol.order);
+                  cgraph_node_name (v), v->order);
      }
  }
  
@@@ -3539,7 -3538,7 +3538,7 @@@ ipcp_decision_stage (struct topo_info *
        {
          struct cgraph_node *v;
          iterate = false;
-         for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
+         for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
            if (cgraph_function_with_gimple_body_p (v)
                && ipcp_versionable_function_p (v))
              iterate |= decide_whether_version_node (v);
@@@ -3612,7 -3611,7 +3611,7 @@@ ipcp_generate_summary (void
    FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
        {
        node->local.versionable
-         = tree_versionable_function_p (node->symbol.decl);
+         = tree_versionable_function_p (node->decl);
        ipa_analyze_node (node);
        }
  }
diff --combined gcc/ipa-devirt.c
index 5f071f10645d449ea01ff526b9878385ac006fbd,80c6b73a4b1802dfeff90bcb9c610b854f84bb65..4877816f9d68c405dc9f97d1328f0596855f0801
@@@ -109,6 -109,7 +109,7 @@@ along with GCC; see the file COPYING3
  #include "system.h"
  #include "coretypes.h"
  #include "tm.h"
+ #include "tree.h"
  #include "cgraph.h"
  #include "tree-pass.h"
  #include "ggc.h"
@@@ -199,7 -200,7 +200,7 @@@ hash_type_name (tree t
  
        if (TREE_CODE (v) == POINTER_PLUS_EXPR)
        {
 -        hash = TREE_INT_CST_LOW (TREE_OPERAND (v, 1));
 +        hash = TREE_INT_CST_ELT (TREE_OPERAND (v, 1), 0);
          v = TREE_OPERAND (TREE_OPERAND (v, 0), 0);
        }
  
@@@ -543,9 -544,9 +544,9 @@@ build_type_inheritance_graph (void
    /* We reconstruct the graph starting of types of all methods seen in the
       the unit.  */
    FOR_EACH_FUNCTION (n)
-     if (DECL_VIRTUAL_P (n->symbol.decl)
-       && symtab_real_symbol_p ((symtab_node)n))
-       get_odr_type (method_class_type (TREE_TYPE (n->symbol.decl)), true);
+     if (DECL_VIRTUAL_P (n->decl)
+       && symtab_real_symbol_p (n))
+       get_odr_type (method_class_type (TREE_TYPE (n->decl)), true);
    if (inheritance_dump_file)
      {
        dump_type_inheritance_graph (inheritance_dump_file);
@@@ -571,8 -572,8 +572,8 @@@ maybe_record_node (vec <cgraph_node *> 
        && !pointer_set_insert (inserted, target)
        && (target_node = cgraph_get_node (target)) != NULL
        && (TREE_PUBLIC (target)
-         || target_node->symbol.definition)
-       && symtab_real_symbol_p ((symtab_node)target_node))
+         || target_node->definition)
+       && symtab_real_symbol_p (target_node))
      {
        pointer_set_insert (cached_polymorphic_call_targets,
                          target_node);
@@@ -626,7 -627,7 +627,7 @@@ record_binfo (vec <cgraph_node *> &node
          if (TREE_CODE (vtable) == POINTER_PLUS_EXPR)
            vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0);
          vnode = varpool_get_node (vtable);
-         if (!vnode || !vnode->symbol.definition)
+         if (!vnode || !vnode->definition)
            return;
        }
        tree target = gimple_get_virt_method_for_binfo (otr_token, type_binfo);
@@@ -760,8 -761,8 +761,8 @@@ devirt_variable_node_removal_hook (stru
                                   void *d ATTRIBUTE_UNUSED)
  {
    if (cached_polymorphic_call_targets
-       && DECL_VIRTUAL_P (n->symbol.decl)
-       && type_in_anonymous_namespace_p (DECL_CONTEXT (n->symbol.decl)))
+       && DECL_VIRTUAL_P (n->decl)
+       && type_in_anonymous_namespace_p (DECL_CONTEXT (n->decl)))
      free_polymorphic_call_targets_hash ();
  }
  
@@@ -890,7 -891,7 +891,7 @@@ dump_possible_polymorphic_call_targets 
           final ? " (full list)" : " (partial list, may call to other unit)");
    for (i = 0; i < targets.length (); i++)
      fprintf (f, " %s/%i", cgraph_node_name (targets[i]),
-            targets[i]->symbol.order);
+            targets[i]->order);
    fprintf (f, "\n");
  }
  
@@@ -916,7 -917,7 +917,7 @@@ possible_polymorphic_call_target_p (tre
  
    /* At a moment we allow middle end to dig out new external declarations
       as a targets of polymorphic calls.  */
-   if (!final && !n->symbol.definition)
+   if (!final && !n->definition)
      return true;
    return false;
  }
@@@ -937,10 -938,10 +938,10 @@@ update_type_inheritance_graph (void
    /* We reconstruct the graph starting of types of all methods seen in the
       the unit.  */
    FOR_EACH_FUNCTION (n)
-     if (DECL_VIRTUAL_P (n->symbol.decl)
-       && !n->symbol.definition
-       && symtab_real_symbol_p ((symtab_node)n))
-       get_odr_type (method_class_type (TREE_TYPE (n->symbol.decl)), true);
+     if (DECL_VIRTUAL_P (n->decl)
+       && !n->definition
+       && symtab_real_symbol_p (n))
+       get_odr_type (method_class_type (TREE_TYPE (n->decl)), true);
    timevar_pop (TV_IPA_INHERITANCE);
  }
  
@@@ -954,13 -955,13 +955,13 @@@ likely_target_p (struct cgraph_node *n
  {
    int flags;
    /* cxa_pure_virtual and similar things are not likely.  */
-   if (TREE_CODE (TREE_TYPE (n->symbol.decl)) != METHOD_TYPE)
+   if (TREE_CODE (TREE_TYPE (n->decl)) != METHOD_TYPE)
      return false;
-   flags = flags_from_decl_or_type (n->symbol.decl);
+   flags = flags_from_decl_or_type (n->decl);
    if (flags & ECF_NORETURN)
      return false;
    if (lookup_attribute ("cold",
-                       DECL_ATTRIBUTES (n->symbol.decl)))
+                       DECL_ATTRIBUTES (n->decl)))
      return false;
    if (n->frequency < NODE_FREQUENCY_NORMAL)
      return false;
@@@ -987,7 -988,7 +988,7 @@@ ipa_devirt (void
        bool update = false;
        if (dump_file && n->indirect_calls)
        fprintf (dump_file, "\n\nProcesing function %s/%i\n",
-                cgraph_node_name (n), n->symbol.order);
+                cgraph_node_name (n), n->order);
        for (e = n->indirect_calls; e; e = e->next_callee)
        if (e->indirect_info->polymorphic)
          {
                  }
                continue;
              }
-           if (!likely_target->symbol.definition)
+           if (!likely_target->definition)
              {
                if (dump_file)
                  fprintf (dump_file, "Target is not an definition\n");
               can handle these just well, it is common for programs to
               incorrectly with headers defining methods they are linked
               with.  */
-           if (DECL_EXTERNAL (likely_target->symbol.decl))
+           if (DECL_EXTERNAL (likely_target->decl))
              {
                if (dump_file)
                  fprintf (dump_file, "Target is external\n");
              }
            if (cgraph_function_body_availability (likely_target)
                <= AVAIL_OVERWRITABLE
-               && symtab_can_be_discarded ((symtab_node) likely_target))
+               && symtab_can_be_discarded (likely_target))
              {
                if (dump_file)
                  fprintf (dump_file, "Target is overwritable\n");
                if (dump_file)
                  fprintf (dump_file,
                           "Speculatively devirtualizing call in %s/%i to %s/%i\n",
-                          cgraph_node_name (n), n->symbol.order,
+                          cgraph_node_name (n), n->order,
                           cgraph_node_name (likely_target),
-                          likely_target->symbol.order);
-               if (!symtab_can_be_discarded ((symtab_node) likely_target))
+                          likely_target->order);
+               if (!symtab_can_be_discarded (likely_target))
                  {
                    cgraph_node *alias;
                    alias = cgraph (symtab_nonoverwritable_alias
-                                    ((symtab_node)likely_target));
+                                    (likely_target));
                    if (alias)
                      likely_target = alias;
                  }
diff --combined gcc/ipa-prop.c
index dae58d9bf15aeb8ccfde4b4a75c229dd29848e8b,d9ea5dc08bfff2cd313e59444c97e76b80f5e931..9761d6e0a999c835fbd6406dec7c604df4f852a3
@@@ -21,16 -21,21 +21,21 @@@ along with GCC; see the file COPYING3
  #include "system.h"
  #include "coretypes.h"
  #include "tree.h"
+ #include "gimple.h"
  #include "langhooks.h"
  #include "ggc.h"
  #include "target.h"
- #include "cgraph.h"
  #include "ipa-prop.h"
- #include "tree-ssa.h"
+ #include "bitmap.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-into-ssa.h"
+ #include "tree-dfa.h"
  #include "tree-pass.h"
  #include "tree-inline.h"
  #include "ipa-inline.h"
- #include "gimple.h"
  #include "flags.h"
  #include "diagnostic.h"
  #include "gimple-pretty-print.h"
@@@ -85,7 -90,7 +90,7 @@@ static alloc_pool ipa_refdesc_pool
  static bool
  ipa_func_spec_opts_forbid_analysis_p (struct cgraph_node *node)
  {
-   tree fs_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node->symbol.decl);
+   tree fs_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node->decl);
    struct cl_optimization *os;
  
    if (!fs_opts)
@@@ -131,7 -136,7 +136,7 @@@ ipa_populate_param_decls (struct cgraph
    tree parm;
    int param_num;
  
-   fndecl = node->symbol.decl;
+   fndecl = node->decl;
    gcc_assert (gimple_has_body_p (fndecl));
    fnargs = DECL_ARGUMENTS (fndecl);
    param_num = 0;
@@@ -196,7 -201,7 +201,7 @@@ ipa_initialize_node_params (struct cgra
  
    if (!info->descriptors.exists ())
      {
-       ipa_alloc_node_params (node, count_formal_params (node->symbol.decl));
+       ipa_alloc_node_params (node, count_formal_params (node->decl));
        ipa_populate_param_decls (node, info->descriptors);
      }
  }
@@@ -288,7 -293,7 +293,7 @@@ ipa_print_node_jump_functions_for_edge 
                       item->offset);
              if (TYPE_P (item->value))
                fprintf (f, "clobber of " HOST_WIDE_INT_PRINT_DEC " bits",
 -                       tree_low_cst (TYPE_SIZE (item->value), 1));
 +                       tree_to_uhwi (TYPE_SIZE (item->value)));
              else
                {
                  fprintf (f, "cst: ");
@@@ -310,16 -315,16 +315,16 @@@ ipa_print_node_jump_functions (FILE *f
    struct cgraph_edge *cs;
  
    fprintf (f, "  Jump functions of caller  %s/%i:\n", cgraph_node_name (node),
-          node->symbol.order);
+          node->order);
    for (cs = node->callees; cs; cs = cs->next_callee)
      {
        if (!ipa_edge_args_info_available_for_edge_p (cs))
        continue;
  
        fprintf (f, "    callsite  %s/%i -> %s/%i : \n",
-              xstrdup (cgraph_node_name (node)), node->symbol.order,
+              xstrdup (cgraph_node_name (node)), node->order,
               xstrdup (cgraph_node_name (cs->callee)),
-              cs->callee->symbol.order);
+              cs->callee->order);
        ipa_print_node_jump_functions_for_edge (f, cs);
      }
  
@@@ -1046,7 -1051,7 +1051,7 @@@ compute_complex_assign_jump_func (struc
        || max_size == -1
        || max_size != size)
      return;
 -  offset += mem_ref_offset (base).low * BITS_PER_UNIT;
 +  offset += mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT;
    ssa = TREE_OPERAND (base, 0);
    if (TREE_CODE (ssa) != SSA_NAME
        || !SSA_NAME_IS_DEFAULT_DEF (ssa)
@@@ -1105,7 -1110,7 +1110,7 @@@ get_ancestor_addr_info (gimple assign, 
        || TREE_CODE (SSA_NAME_VAR (parm)) != PARM_DECL)
      return NULL_TREE;
  
 -  *offset += mem_ref_offset (expr).low * BITS_PER_UNIT;
 +  *offset += mem_ref_offset (expr).to_short_addr () * BITS_PER_UNIT;
    *obj_p = obj;
    return expr;
  }
@@@ -1251,7 -1256,7 +1256,7 @@@ type_like_member_ptr_p (tree type, tre
    fld = TYPE_FIELDS (type);
    if (!fld || !POINTER_TYPE_P (TREE_TYPE (fld))
        || TREE_CODE (TREE_TYPE (TREE_TYPE (fld))) != METHOD_TYPE
 -      || !host_integerp (DECL_FIELD_OFFSET (fld), 1))
 +      || !tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
      return false;
  
    if (method_ptr)
  
    fld = DECL_CHAIN (fld);
    if (!fld || INTEGRAL_TYPE_P (fld)
 -      || !host_integerp (DECL_FIELD_OFFSET (fld), 1))
 +      || !tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
      return false;
    if (delta)
      *delta = fld;
@@@ -1329,13 -1334,13 +1334,13 @@@ determine_known_aggregate_parts (gimpl
        if (TREE_CODE (arg) == SSA_NAME)
        {
          tree type_size;
 -          if (!host_integerp (TYPE_SIZE (TREE_TYPE (TREE_TYPE (arg))), 1))
 +          if (!tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (TREE_TYPE (arg)))))
              return;
          check_ref = true;
          arg_base = arg;
          arg_offset = 0;
          type_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (arg)));
 -        arg_size = tree_low_cst (type_size, 1);
 +        arg_size = tree_to_uhwi (type_size);
          ao_ref_init_from_ptr_and_size (&r, arg_base, NULL_TREE);
        }
        else if (TREE_CODE (arg) == ADDR_EXPR)
@@@ -1508,7 -1513,7 +1513,7 @@@ ipa_get_callee_param_type (struct cgrap
  {
    int n;
    tree type = (e->callee
-              ? TREE_TYPE (e->callee->symbol.decl)
+              ? TREE_TYPE (e->callee->decl)
               : gimple_call_fntype (e->call_stmt));
    tree t = TYPE_ARG_TYPES (type);
  
      return TREE_VALUE (t);
    if (!e->callee)
      return NULL;
-   t = DECL_ARGUMENTS (e->callee->symbol.decl);
+   t = DECL_ARGUMENTS (e->callee->decl);
    for (n = 0; n < i; n++)
      {
        if (!t)
@@@ -1642,7 -1647,7 +1647,7 @@@ ipa_compute_jump_functions (struct cgra
                                                                  NULL);
        /* We do not need to bother analyzing calls to unknown
         functions unless they may become known during lto/whopr.  */
-       if (!callee->symbol.definition && !flag_lto)
+       if (!callee->definition && !flag_lto)
        continue;
        ipa_compute_jump_functions_for_edge (parms_ainfo, cs);
      }
@@@ -1982,7 -1987,7 +1987,7 @@@ ipa_analyze_virtual_call_uses (struct c
    cs = ipa_note_param_call (node, index, call);
    ii = cs->indirect_info;
    ii->offset = anc_offset;
 -  ii->otr_token = tree_low_cst (OBJ_TYPE_REF_TOKEN (target), 1);
 +  ii->otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
    ii->otr_type = obj_type_ref_class (target);
    ii->polymorphic = 1;
  }
@@@ -2051,7 -2056,7 +2056,7 @@@ static voi
  ipa_analyze_params_uses (struct cgraph_node *node,
                         struct param_analysis_info *parms_ainfo)
  {
-   tree decl = node->symbol.decl;
+   tree decl = node->decl;
    basic_block bb;
    struct function *func;
    gimple_stmt_iterator gsi;
         the flag during modification analysis.  */
        if (is_gimple_reg (parm))
        {
-         tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->symbol.decl),
+         tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl),
                                       parm);
          if (ddef && !has_zero_uses (ddef))
            {
@@@ -2160,7 -2165,7 +2165,7 @@@ ipa_analyze_node (struct cgraph_node *n
    ipa_check_create_node_params ();
    ipa_check_create_edge_args ();
    info = IPA_NODE_REF (node);
-   push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
    ipa_initialize_node_params (node);
  
    param_count = ipa_get_param_count (info);
@@@ -2194,7 -2199,7 +2199,7 @@@ ipa_intraprocedural_devirtualization (g
    if (!binfo)
      return NULL_TREE;
    token = OBJ_TYPE_REF_TOKEN (otr);
 -  fndecl = gimple_get_virt_method_for_binfo (tree_low_cst (token, 1),
 +  fndecl = gimple_get_virt_method_for_binfo (tree_to_uhwi (token),
                                             binfo);
  #ifdef ENABLE_CHECKING
    if (fndecl)
@@@ -2413,7 -2418,7 +2418,7 @@@ ipa_make_edge_direct_to_target (struct 
          if (dump_file)
            fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
                                " in %s/%i, making it unreachable.\n",
-                    cgraph_node_name (ie->caller), ie->caller->symbol.order);
+                    cgraph_node_name (ie->caller), ie->caller->order);
          target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
          callee = cgraph_get_create_node (target);
          unreachable = true;
            fprintf (dump_file, "ipa-prop: Discovered call to a known target "
                     "(%s/%i -> %s/%i) but can not refer to it. Giving up.\n",
                     xstrdup (cgraph_node_name (ie->caller)),
-                    ie->caller->symbol.order,
+                    ie->caller->order,
                     xstrdup (cgraph_node_name (ie->callee)),
-                    ie->callee->symbol.order);
+                    ie->callee->order);
          return NULL;
        }
        callee = cgraph_get_create_real_symbol_node (target);
               "(%s/%i -> %s/%i), for stmt ",
               ie->indirect_info->polymorphic ? "a virtual" : "an indirect",
               xstrdup (cgraph_node_name (ie->caller)),
-              ie->caller->symbol.order,
+              ie->caller->order,
               xstrdup (cgraph_node_name (callee)),
-              callee->symbol.order);
+              callee->order);
        if (ie->call_stmt)
        print_gimple_stmt (dump_file, ie->call_stmt, 2, TDF_SLIM);
        else
@@@ -2507,7 -2512,7 +2512,7 @@@ ipa_find_agg_cst_for_param (struct ipa_
     successfully found and removed.  */
  
  static bool
- remove_described_reference (symtab_node symbol, struct ipa_cst_ref_desc *rdesc)
+ remove_described_reference (symtab_node *symbol, struct ipa_cst_ref_desc *rdesc)
  {
    struct ipa_ref *to_del;
    struct cgraph_edge *origin;
    origin = rdesc->cs;
    if (!origin)
      return false;
-   to_del = ipa_find_reference ((symtab_node) origin->caller, symbol,
+   to_del = ipa_find_reference (origin->caller, symbol,
                               origin->call_stmt, origin->lto_stmt_uid);
    if (!to_del)
      return false;
    if (dump_file)
      fprintf (dump_file, "ipa-prop: Removed a reference from %s/%i to %s.\n",
             xstrdup (cgraph_node_name (origin->caller)),
-            origin->caller->symbol.order, xstrdup (symtab_node_name (symbol)));
+            origin->caller->order, xstrdup (symtab_node_name (symbol)));
    return true;
  }
  
@@@ -2572,7 -2577,7 +2577,7 @@@ try_decrement_rdesc_refcount (struct ip
        && (rdesc = jfunc_rdesc_usable (jfunc))
        && --rdesc->refcount == 0)
      {
-       symtab_node symbol = (symtab_node) cgraph_node_for_jfunc (jfunc);
+       symtab_node *symbol = cgraph_node_for_jfunc (jfunc);
        if (!symbol)
        return false;
  
@@@ -2732,7 -2737,7 +2737,7 @@@ update_indirect_edges_after_inlining (s
            new_direct_edge->call_stmt_cannot_inline_p
              = !gimple_check_call_matching_types (
                  new_direct_edge->call_stmt,
-                 new_direct_edge->callee->symbol.decl, false);
+                 new_direct_edge->callee->decl, false);
          if (new_edges)
            {
              new_edges->safe_push (new_direct_edge);
@@@ -2848,15 -2853,15 +2853,15 @@@ propagate_controlled_uses (struct cgrap
              if (t && TREE_CODE (t) == ADDR_EXPR
                  && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
                  && (n = cgraph_get_node (TREE_OPERAND (t, 0)))
-                 && (ref = ipa_find_reference ((symtab_node) new_root,
-                                               (symtab_node) n, NULL, 0)))
+                 && (ref = ipa_find_reference (new_root,
+                                               n, NULL, 0)))
                {
                  if (dump_file)
                    fprintf (dump_file, "ipa-prop: Removing cloning-created "
                             "reference from %s/%i to %s/%i.\n",
                             xstrdup (cgraph_node_name (new_root)),
-                            new_root->symbol.order,
-                            xstrdup (cgraph_node_name (n)), n->symbol.order);
+                            new_root->order,
+                            xstrdup (cgraph_node_name (n)), n->order);
                  ipa_remove_reference (ref);
                }
            }
                {
                  struct cgraph_node *clone;
                  bool ok;
-                 ok = remove_described_reference ((symtab_node) n, rdesc);
+                 ok = remove_described_reference (n, rdesc);
                  gcc_checking_assert (ok);
  
                  clone = cs->caller;
                         && IPA_NODE_REF (clone)->ipcp_orig_node)
                    {
                      struct ipa_ref *ref;
-                     ref = ipa_find_reference ((symtab_node) clone,
-                                               (symtab_node) n, NULL, 0);
+                     ref = ipa_find_reference (clone,
+                                               n, NULL, 0);
                      if (ref)
                        {
                          if (dump_file)
                                     "cloning-created reference "
                                     "from %s/%i to %s/%i.\n",
                                     xstrdup (cgraph_node_name (clone)),
-                                    clone->symbol.order,
+                                    clone->order,
                                     xstrdup (cgraph_node_name (n)),
-                                    n->symbol.order);
+                                    n->order);
                          ipa_remove_reference (ref);
                        }
                      clone = clone->callers->caller;
@@@ -3092,12 -3097,12 +3097,12 @@@ ipa_edge_duplication_hook (struct cgrap
          else if (src->caller == dst->caller)
            {
              struct ipa_ref *ref;
-             symtab_node n = (symtab_node) cgraph_node_for_jfunc (src_jf);
+             symtab_node *n = cgraph_node_for_jfunc (src_jf);
              gcc_checking_assert (n);
-             ref = ipa_find_reference ((symtab_node) src->caller, n,
+             ref = ipa_find_reference (src->caller, n,
                                        src->call_stmt, src->lto_stmt_uid);
              gcc_checking_assert (ref);
-             ipa_clone_ref (ref, (symtab_node) dst->caller, ref->stmt);
+             ipa_clone_ref (ref, dst->caller, ref->stmt);
  
              gcc_checking_assert (ipa_refdesc_pool);
              struct ipa_cst_ref_desc *dst_rdesc
@@@ -3278,11 -3283,11 +3283,11 @@@ ipa_print_node_params (FILE *f, struct 
    int i, count;
    struct ipa_node_params *info;
  
-   if (!node->symbol.definition)
+   if (!node->definition)
      return;
    info = IPA_NODE_REF (node);
    fprintf (f, "  function  %s/%i parameter descriptors:\n",
-          cgraph_node_name (node), node->symbol.order);
+          cgraph_node_name (node), node->order);
    count = ipa_get_param_count (info);
    for (i = 0; i < count; i++)
      {
@@@ -3525,8 -3530,8 +3530,8 @@@ ipa_modify_call_arguments (struct cgrap
  
    len = adjustments.length ();
    vargs.create (len);
-   callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->symbol.decl;
-   ipa_remove_stmt_references ((symtab_node) current_node, stmt);
+   callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl;
+   ipa_remove_stmt_references (current_node, stmt);
  
    gsi = gsi_for_stmt (stmt);
    prev_gsi = gsi;
                  if (TYPE_ALIGN (type) > align)
                    align = TYPE_ALIGN (type);
                }
 -            misalign += (tree_to_double_int (off)
 -                         .sext (TYPE_PRECISION (TREE_TYPE (off))).low
 -                         * BITS_PER_UNIT);
 +            misalign += (offset_int::from (off, SIGNED)
 +                         * BITS_PER_UNIT).to_short_addr ();
              misalign = misalign & (align - 1);
              if (misalign != 0)
                align = (misalign & -misalign);
@@@ -4117,7 -4123,7 +4122,7 @@@ ipa_write_node_info (struct output_bloc
    struct bitpack_d bp;
  
    encoder = ob->decl_state->symtab_node_encoder;
-   node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
+   node_ref = lto_symtab_encoder_encode (encoder, node);
    streamer_write_uhwi (ob, node_ref);
  
    streamer_write_uhwi (ob, ipa_get_param_count (info));
@@@ -4281,7 -4287,7 +4286,7 @@@ ipa_prop_read_section (struct lto_file_
        index = streamer_read_uhwi (&ib_main);
        encoder = file_data->symtab_node_encoder;
        node = cgraph (lto_symtab_encoder_deref (encoder, index));
-       gcc_assert (node->symbol.definition);
+       gcc_assert (node->definition);
        ipa_read_node_info (&ib_main, node, data_in);
      }
    lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
@@@ -4333,7 -4339,7 +4338,7 @@@ write_agg_replacement_chain (struct out
  
    aggvals = ipa_get_agg_replacements_for_node (node);
    encoder = ob->decl_state->symtab_node_encoder;
-   node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
+   node_ref = lto_symtab_encoder_encode (encoder, node);
    streamer_write_uhwi (ob, node_ref);
  
    for (av = aggvals; av; av = av->next)
@@@ -4457,7 -4463,7 +4462,7 @@@ read_replacements_section (struct lto_f
        index = streamer_read_uhwi (&ib_main);
        encoder = file_data->symtab_node_encoder;
        node = cgraph (lto_symtab_encoder_deref (encoder, index));
-       gcc_assert (node->symbol.definition);
+       gcc_assert (node->definition);
        read_agg_replacement_chain (&ib_main, node, data_in);
      }
    lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
@@@ -4539,12 -4545,12 +4544,12 @@@ ipcp_transform_function (struct cgraph_
  
    if (dump_file)
      fprintf (dump_file, "Modification phase of node %s/%i\n",
-            cgraph_node_name (node), node->symbol.order);
+            cgraph_node_name (node), node->order);
  
    aggval = ipa_get_agg_replacements_for_node (node);
    if (!aggval)
        return 0;
-   param_count = count_formal_params (node->symbol.decl);
+   param_count = count_formal_params (node->decl);
    if (param_count == 0)
      return 0;
    adjust_agg_replacement_values (node, aggval);
diff --combined gcc/ipa-utils.h
index 15f312e606572e7cf89c71019b5ba69ced3217f9,cc72619348e9d899c81285881754d9d77b316642..ca8b87290b5d58b2d61679003295905c9d0138fa
@@@ -20,7 -20,6 +20,6 @@@ along with GCC; see the file COPYING3
  
  #ifndef GCC_IPA_UTILS_H
  #define GCC_IPA_UTILS_H
- #include "tree.h"
  #include "cgraph.h"
  
  struct ipa_dfs_info {
@@@ -118,8 -117,8 +117,8 @@@ possible_polymorphic_call_target_p (tre
                                    struct cgraph_node *n)
  {
    return possible_polymorphic_call_target_p (obj_type_ref_class (call),
 -                                           tree_low_cst
 -                                              (OBJ_TYPE_REF_TOKEN (call), 1),
 +                                           tree_to_uhwi
 +                                              (OBJ_TYPE_REF_TOKEN (call)),
                                             n);
  }
  #endif  /* GCC_IPA_UTILS_H  */
diff --combined gcc/loop-unroll.c
index f0864111842fd1974b568d60c7701d9fbfdbe8bb,40f06dbbca32071e1a0eec67b5fbbe1c117bb7df..ac43f582d36ff19d0751c9e9de693b75d640e150
@@@ -22,6 -22,7 +22,7 @@@ along with GCC; see the file COPYING3
  #include "coretypes.h"
  #include "tm.h"
  #include "rtl.h"
+ #include "tree.h"
  #include "hard-reg-set.h"
  #include "obstack.h"
  #include "basic-block.h"
@@@ -646,7 -647,7 +647,7 @@@ decide_unroll_constant_iterations (stru
  {
    unsigned nunroll, nunroll_by_av, best_copies, best_unroll = 0, n_copies, i;
    struct niter_desc *desc;
 -  double_int iterations;
 +  widest_int iterations;
  
    if (!(flags & UAP_UNROLL))
      {
    if (desc->niter < 2 * nunroll
        || ((get_estimated_loop_iterations (loop, &iterations)
           || get_max_loop_iterations (loop, &iterations))
 -        && iterations.ult (double_int::from_shwi (2 * nunroll))))
 +        && wi::ltu_p (iterations, 2 * nunroll)))
      {
        if (dump_file)
        fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");
@@@ -817,10 -818,11 +818,10 @@@ unroll_loop_constant_iterations (struc
  
          desc->noloop_assumptions = NULL_RTX;
          desc->niter -= exit_mod;
 -        loop->nb_iterations_upper_bound -= double_int::from_uhwi (exit_mod);
 +        loop->nb_iterations_upper_bound -= exit_mod;
          if (loop->any_estimate
 -            && double_int::from_uhwi (exit_mod).ule
 -                 (loop->nb_iterations_estimate))
 -          loop->nb_iterations_estimate -= double_int::from_uhwi (exit_mod);
 +            && wi::leu_p (exit_mod, loop->nb_iterations_estimate))
 +          loop->nb_iterations_estimate -= exit_mod;
          else
            loop->any_estimate = false;
        }
            apply_opt_in_copies (opt_info, exit_mod + 1, false, false);
  
          desc->niter -= exit_mod + 1;
 -        loop->nb_iterations_upper_bound -= double_int::from_uhwi (exit_mod + 1);
 +        loop->nb_iterations_upper_bound -= exit_mod + 1;
          if (loop->any_estimate
 -            && double_int::from_uhwi (exit_mod + 1).ule
 -                 (loop->nb_iterations_estimate))
 -          loop->nb_iterations_estimate -= double_int::from_uhwi (exit_mod + 1);
 +            && wi::leu_p (exit_mod + 1, loop->nb_iterations_estimate))
 +          loop->nb_iterations_estimate -= exit_mod + 1;
          else
            loop->any_estimate = false;
          desc->noloop_assumptions = NULL_RTX;
  
    desc->niter /= max_unroll + 1;
    loop->nb_iterations_upper_bound
 -    = loop->nb_iterations_upper_bound.udiv (double_int::from_uhwi (max_unroll
 -                                                                 + 1),
 -                                          TRUNC_DIV_EXPR);
 +    = wi::udiv_trunc (loop->nb_iterations_upper_bound, max_unroll + 1);
    if (loop->any_estimate)
      loop->nb_iterations_estimate
 -      = loop->nb_iterations_estimate.udiv (double_int::from_uhwi (max_unroll
 -                                                                + 1),
 -                                         TRUNC_DIV_EXPR);
 +      = wi::udiv_trunc (loop->nb_iterations_estimate, max_unroll + 1);
    desc->niter_expr = GEN_INT (desc->niter);
  
    /* Remove the edges.  */
@@@ -939,7 -946,7 +940,7 @@@ decide_unroll_runtime_iterations (struc
  {
    unsigned nunroll, nunroll_by_av, i;
    struct niter_desc *desc;
 -  double_int iterations;
 +  widest_int iterations;
  
    if (!(flags & UAP_UNROLL))
      {
    /* Check whether the loop rolls.  */
    if ((get_estimated_loop_iterations (loop, &iterations)
         || get_max_loop_iterations (loop, &iterations))
 -      && iterations.ult (double_int::from_shwi (2 * nunroll)))
 +      && wi::ltu_p (iterations, 2 * nunroll))
      {
        if (dump_file)
        fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");
@@@ -1305,10 -1312,14 +1306,10 @@@ unroll_loop_runtime_iterations (struct 
      simplify_gen_binary (UDIV, desc->mode, old_niter,
                         gen_int_mode (max_unroll + 1, desc->mode));
    loop->nb_iterations_upper_bound
 -    = loop->nb_iterations_upper_bound.udiv (double_int::from_uhwi (max_unroll
 -                                                                 + 1),
 -                                          TRUNC_DIV_EXPR);
 +    = wi::udiv_trunc (loop->nb_iterations_upper_bound, max_unroll + 1);
    if (loop->any_estimate)
      loop->nb_iterations_estimate
 -      = loop->nb_iterations_estimate.udiv (double_int::from_uhwi (max_unroll
 -                                                                + 1),
 -                                         TRUNC_DIV_EXPR);
 +      = wi::udiv_trunc (loop->nb_iterations_estimate, max_unroll + 1);
    if (exit_at_end)
      {
        desc->niter_expr =
        desc->noloop_assumptions = NULL_RTX;
        --loop->nb_iterations_upper_bound;
        if (loop->any_estimate
 -        && loop->nb_iterations_estimate != double_int_zero)
 +        && loop->nb_iterations_estimate != 0)
        --loop->nb_iterations_estimate;
        else
        loop->any_estimate = false;
@@@ -1336,7 -1347,7 +1337,7 @@@ static voi
  decide_peel_simple (struct loop *loop, int flags)
  {
    unsigned npeel;
 -  double_int iterations;
 +  widest_int iterations;
  
    if (!(flags & UAP_PEEL))
      {
    /* If we have realistic estimate on number of iterations, use it.  */
    if (get_estimated_loop_iterations (loop, &iterations))
      {
 -      if (double_int::from_shwi (npeel).ule (iterations))
 +      /* TODO: unsigned/signed confusion */
 +      if (wi::leu_p (npeel, iterations))
        {
          if (dump_file)
            {
    /* If we have small enough bound on iterations, we can still peel (completely
       unroll).  */
    else if (get_max_loop_iterations (loop, &iterations)
 -           && iterations.ult (double_int::from_shwi (npeel)))
 +           && wi::ltu_p (iterations, npeel))
      npeel = iterations.to_shwi () + 1;
    else
      {
@@@ -1492,7 -1502,7 +1493,7 @@@ decide_unroll_stupid (struct loop *loop
  {
    unsigned nunroll, nunroll_by_av, i;
    struct niter_desc *desc;
 -  double_int iterations;
 +  widest_int iterations;
  
    if (!(flags & UAP_UNROLL_ALL))
      {
    /* Check whether the loop rolls.  */
    if ((get_estimated_loop_iterations (loop, &iterations)
         || get_max_loop_iterations (loop, &iterations))
 -      && iterations.ult (double_int::from_shwi (2 * nunroll)))
 +      && wi::ltu_p (iterations, 2 * nunroll))
      {
        if (dump_file)
        fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");
diff --combined gcc/lto-streamer-in.c
index 8975cd6dd7035037feb1398ef6d470fdd5d83a49,d4a52a766712456eac71064ad30da65729f09201..bf823d0dcba00d20cee04decba6b541c808e9804
@@@ -32,9 -32,14 +32,14 @@@ along with GCC; see the file COPYING3
  #include "input.h"
  #include "hashtab.h"
  #include "basic-block.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-ssanames.h"
+ #include "tree-into-ssa.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "tree-pass.h"
- #include "cgraph.h"
  #include "function.h"
  #include "ggc.h"
  #include "diagnostic.h"
@@@ -695,26 -700,14 +700,26 @@@ input_cfg (struct lto_input_block *ib, 
        loop->any_upper_bound = streamer_read_hwi (ib);
        if (loop->any_upper_bound)
        {
 -        loop->nb_iterations_upper_bound.low = streamer_read_uhwi (ib);
 -        loop->nb_iterations_upper_bound.high = streamer_read_hwi (ib);
 +        HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
 +        int i;
 +        int prec ATTRIBUTE_UNUSED = streamer_read_uhwi (ib);
 +        int len = streamer_read_uhwi (ib);
 +        for (i = 0; i < len; i++)
 +          a[i] = streamer_read_hwi (ib);
 +        
 +        loop->nb_iterations_upper_bound = widest_int::from_array (a, len);
        }
        loop->any_estimate = streamer_read_hwi (ib);
        if (loop->any_estimate)
        {
 -        loop->nb_iterations_estimate.low = streamer_read_uhwi (ib);
 -        loop->nb_iterations_estimate.high = streamer_read_hwi (ib);
 +        HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
 +        int i;
 +        int prec ATTRIBUTE_UNUSED = streamer_read_uhwi (ib);
 +        int len = streamer_read_uhwi (ib);
 +        for (i = 0; i < len; i++)
 +          a[i] = streamer_read_hwi (ib);
 +        
 +        loop->nb_iterations_estimate = widest_int::from_array (a, len);
        }
  
        place_new_loop (fn, loop);
@@@ -791,7 -784,7 +796,7 @@@ fixup_call_stmt_edges_1 (struct cgraph_
          fatal_error ("Cgraph edge statement index not found");
      }
    for (i = 0;
-        ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref);
+        ipa_ref_list_reference_iterate (&node->ref_list, i, ref);
         i++)
      if (ref->lto_stmt_uid)
        {
@@@ -814,7 -807,7 +819,7 @@@ fixup_call_stmt_edges (struct cgraph_no
  
    while (orig->clone_of)
      orig = orig->clone_of;
-   fn = DECL_STRUCT_FUNCTION (orig->symbol.decl);
+   fn = DECL_STRUCT_FUNCTION (orig->decl);
  
    fixup_call_stmt_edges_1 (orig, stmts, fn);
    if (orig->clones)
@@@ -1031,7 -1024,7 +1036,7 @@@ lto_read_body (struct lto_file_decl_dat
    int string_offset;
    struct lto_input_block ib_cfg;
    struct lto_input_block ib_main;
-   tree fn_decl = node->symbol.decl;
+   tree fn_decl = node->decl;
  
    header = (const struct lto_function_header *) data;
    cfg_offset = sizeof (struct lto_function_header);
@@@ -1262,17 -1255,12 +1267,17 @@@ lto_input_tree_1 (struct lto_input_bloc
      }
    else if (tag == LTO_integer_cst)
      {
 -      /* For shared integer constants in singletons we can use the existing
 -         tree integer constant merging code.  */
 +      /* For shared integer constants in singletons we can use the
 +         existing tree integer constant merging code.  */
        tree type = stream_read_tree (ib, data_in);
 -      unsigned HOST_WIDE_INT low = streamer_read_uhwi (ib);
 -      HOST_WIDE_INT high = streamer_read_hwi (ib);
 -      result = build_int_cst_wide (type, low, high);
 +      unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
 +      unsigned HOST_WIDE_INT i;
 +      HOST_WIDE_INT a[WIDE_INT_MAX_ELTS]; 
 +
 +      for (i = 0; i < len; i++)
 +      a[i] = streamer_read_hwi (ib);
 +      result = wide_int_to_tree (type, wide_int::from_array
 +                               (a, len, TYPE_PRECISION (type)));
        streamer_tree_cache_append (data_in->reader_cache, result, hash);
      }
    else if (tag == LTO_tree_scc)
diff --combined gcc/lto-streamer-out.c
index f6af70871940b24a795502666407cfce89526997,55186234d8ca5133cfed439779d248bb07118a00..ff6d345fe326c6a227e108bf4882f98e9316a47f
@@@ -31,9 -31,10 +31,10 @@@ along with GCC; see the file COPYING3
  #include "input.h"
  #include "hashtab.h"
  #include "basic-block.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-ssanames.h"
  #include "tree-pass.h"
- #include "cgraph.h"
  #include "function.h"
  #include "ggc.h"
  #include "diagnostic-core.h"
@@@ -710,11 -711,8 +711,11 @@@ hash_tree (struct streamer_tree_cache_
  
    if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
      {
 -      v = iterative_hash_host_wide_int (TREE_INT_CST_LOW (t), v);
 -      v = iterative_hash_host_wide_int (TREE_INT_CST_HIGH (t), v);
 +      int i; 
 +      v = iterative_hash_host_wide_int (TREE_INT_CST_NUNITS (t), v);
 +      v = iterative_hash_host_wide_int (TREE_INT_CST_EXT_NUNITS (t), v);
 +      for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
 +      v = iterative_hash_host_wide_int (TREE_INT_CST_ELT (t, i), v);
      }
  
    if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
@@@ -1630,24 -1628,14 +1631,24 @@@ output_cfg (struct output_block *ob, st
        streamer_write_hwi (ob, loop->any_upper_bound);
        if (loop->any_upper_bound)
        {
 -        streamer_write_uhwi (ob, loop->nb_iterations_upper_bound.low);
 -        streamer_write_hwi (ob, loop->nb_iterations_upper_bound.high);
 +        int len = loop->nb_iterations_upper_bound.get_len ();
 +        int i;
 +
 +        streamer_write_uhwi (ob, loop->nb_iterations_upper_bound.get_precision ());
 +        streamer_write_uhwi (ob, len);
 +        for (i = 0; i < len; i++)
 +          streamer_write_hwi (ob, loop->nb_iterations_upper_bound.elt (i));
        }
        streamer_write_hwi (ob, loop->any_estimate);
        if (loop->any_estimate)
        {
 -        streamer_write_uhwi (ob, loop->nb_iterations_estimate.low);
 -        streamer_write_hwi (ob, loop->nb_iterations_estimate.high);
 +        int len = loop->nb_iterations_estimate.get_len ();
 +        int i;
 +
 +        streamer_write_uhwi (ob, loop->nb_iterations_estimate.get_precision ());
 +        streamer_write_uhwi (ob, len);
 +        for (i = 0; i < len; i++)
 +          streamer_write_hwi (ob, loop->nb_iterations_estimate.elt (i));
        }
      }
  
@@@ -1763,7 -1751,7 +1764,7 @@@ output_function (struct cgraph_node *no
    basic_block bb;
    struct output_block *ob;
  
-   function = node->symbol.decl;
+   function = node->decl;
    fn = DECL_STRUCT_FUNCTION (function);
    ob = create_output_block (LTO_section_function_body);
  
@@@ -1922,8 -1910,8 +1923,8 @@@ lto_output_toplevel_asms (void
  static void
  copy_function (struct cgraph_node *node)
  {
-   tree function = node->symbol.decl;
-   struct lto_file_decl_data *file_data = node->symbol.lto_file_data;
+   tree function = node->decl;
+   struct lto_file_decl_data *file_data = node->lto_file_data;
    struct lto_output_stream *output_stream = XCNEW (struct lto_output_stream);
    const char *data;
    size_t len;
  
    /* Copy decls. */
    in_state =
-     lto_get_function_in_decl_state (node->symbol.lto_file_data, function);
+     lto_get_function_in_decl_state (node->lto_file_data, function);
    gcc_assert (in_state);
  
    for (i = 0; i < LTO_N_DECL_STREAMS; i++)
@@@ -1994,25 -1982,25 +1995,25 @@@ lto_output (void
    /* Process only the functions with bodies.  */
    for (i = 0; i < n_nodes; i++)
      {
-       symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+       symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
        cgraph_node *node = dyn_cast <cgraph_node> (snode);
        if (node
          && lto_symtab_encoder_encode_body_p (encoder, node)
-         && !node->symbol.alias)
+         && !node->alias)
        {
  #ifdef ENABLE_CHECKING
-         gcc_assert (!bitmap_bit_p (output, DECL_UID (node->symbol.decl)));
-         bitmap_set_bit (output, DECL_UID (node->symbol.decl));
+         gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
+         bitmap_set_bit (output, DECL_UID (node->decl));
  #endif
          decl_state = lto_new_out_decl_state ();
          lto_push_out_decl_state (decl_state);
-         if (gimple_has_body_p (node->symbol.decl) || !flag_wpa)
+         if (gimple_has_body_p (node->decl) || !flag_wpa)
            output_function (node);
          else
            copy_function (node);
          gcc_assert (lto_get_out_decl_state () == decl_state);
          lto_pop_out_decl_state ();
-         lto_record_function_out_decl_state (node->symbol.decl, decl_state);
+         lto_record_function_out_decl_state (node->decl, decl_state);
        }
      }
  
@@@ -2244,10 -2232,10 +2245,10 @@@ write_symbol (struct streamer_tree_cach
  
        /* When something is defined, it should have node attached.  */
        gcc_assert (alias || TREE_CODE (t) != VAR_DECL
-                 || varpool_get_node (t)->symbol.definition);
+                 || varpool_get_node (t)->definition);
        gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL
                  || (cgraph_get_node (t)
-                     && cgraph_get_node (t)->symbol.definition));
+                     && cgraph_get_node (t)->definition));
      }
  
    /* Imitate what default_elf_asm_output_external do.
    if (kind == GCCPK_COMMON
        && DECL_SIZE_UNIT (t)
        && TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST)
 -    size = TREE_INT_CST_LOW (DECL_SIZE_UNIT (t));
 +    size = tree_to_hwi (DECL_SIZE_UNIT (t));
    else
      size = 0;
  
  /* Return true if NODE should appear in the plugin symbol table.  */
  
  bool
- output_symbol_p (symtab_node node)
+ output_symbol_p (symtab_node *node)
  {
    struct cgraph_node *cnode;
    if (!symtab_real_symbol_p (node))
       and devirtualization.  We do not want to see them in symbol table as
       references unless they are really used.  */
    cnode = dyn_cast <cgraph_node> (node);
-   if (cnode && (!node->symbol.definition || DECL_EXTERNAL (cnode->symbol.decl))
+   if (cnode && (!node->definition || DECL_EXTERNAL (cnode->decl))
        && cnode->callers)
      return true;
  
      part of the compilation unit until they are used by folding.  Some symbols,
      like references to external construction vtables can not be referred to at all.
      We decide this at can_refer_decl_in_current_unit_p.  */
-  if (!node->symbol.definition || DECL_EXTERNAL (node->symbol.decl))
+  if (!node->definition || DECL_EXTERNAL (node->decl))
      {
        int i;
        struct ipa_ref *ref;
-       for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+       for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
                                                  i, ref); i++)
        {
          if (ref->use == IPA_REF_ALIAS)
            continue;
            if (is_a <cgraph_node> (ref->referring))
            return true;
-         if (!DECL_EXTERNAL (ref->referring->symbol.decl))
+         if (!DECL_EXTERNAL (ref->referring->decl))
            return true;
        }
        return false;
@@@ -2364,20 -2352,20 +2365,20 @@@ produce_symtab (struct output_block *ob
    for (lsei = lsei_start (encoder);
         !lsei_end_p (lsei); lsei_next (&lsei))
      {
-       symtab_node node = lsei_node (lsei);
+       symtab_node *node = lsei_node (lsei);
  
-       if (!output_symbol_p (node) || DECL_EXTERNAL (node->symbol.decl))
+       if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
        continue;
-       write_symbol (cache, &stream, node->symbol.decl, seen, false);
+       write_symbol (cache, &stream, node->decl, seen, false);
      }
    for (lsei = lsei_start (encoder);
         !lsei_end_p (lsei); lsei_next (&lsei))
      {
-       symtab_node node = lsei_node (lsei);
+       symtab_node *node = lsei_node (lsei);
  
-       if (!output_symbol_p (node) || !DECL_EXTERNAL (node->symbol.decl))
+       if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
        continue;
-       write_symbol (cache, &stream, node->symbol.decl, seen, false);
+       write_symbol (cache, &stream, node->decl, seen, false);
      }
  
    lto_write_stream (&stream);
diff --combined gcc/lto/lto-lang.c
index de9bda9ba6709ec850507f8a974169a46b253e17,b56c22b8a87d01c3b3fe7d8cd924687e1a6bcc46..55bf1787a3f62fe9e1f0d6a76eb544d9f3fc77ce
@@@ -35,6 -35,7 +35,7 @@@ along with GCC; see the file COPYING3
  #include "diagnostic-core.h"
  #include "toplev.h"
  #include "lto-streamer.h"
+ #include "cilk.h"
  
  static tree lto_type_for_size (unsigned, int);
  
@@@ -315,10 -316,11 +316,10 @@@ static boo
  get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
  {
    /* Verify the arg number is a constant.  */
 -  if (TREE_CODE (arg_num_expr) != INTEGER_CST
 -      || TREE_INT_CST_HIGH (arg_num_expr) != 0)
 +  if (!cst_fits_uhwi_p (arg_num_expr))
      return false;
  
 -  *valp = TREE_INT_CST_LOW (arg_num_expr);
 +  *valp = tree_to_hwi (arg_num_expr);
    return true;
  }
  
@@@ -1173,6 -1175,9 +1174,9 @@@ lto_init (void
        lto_define_builtins (va_list_type_node,
                           build_reference_type (va_list_type_node));
      }
+   
+   if (flag_enable_cilkplus)
+     cilk_init_builtins ();
  
    targetm.init_builtins ();
    build_common_builtin_nodes ();
diff --combined gcc/lto/lto.c
index 1168d7b4268e307a14e136f4f54603444610f64d,62856d085b7a6477d5ad5403f038c273c1c1ccdf..0473565549b5720073797b1ed567ac86ad33f949
@@@ -171,7 -171,7 +171,7 @@@ has_analyzed_clone_p (struct cgraph_nod
    if (node)
      while (node != orig)
        {
-       if (node->symbol.analyzed)
+       if (node->analyzed)
          return true;
        if (node->clones)
          node = node->clones;
@@@ -195,10 -195,10 +195,10 @@@ lto_materialize_function (struct cgraph
  {
    tree decl;
  
-   decl = node->symbol.decl;
+   decl = node->decl;
    /* Read in functions with body (analyzed nodes)
       and also functions that are needed to produce virtual clones.  */
-   if ((cgraph_function_with_gimple_body_p (node) && node->symbol.analyzed)
+   if ((cgraph_function_with_gimple_body_p (node) && node->analyzed)
        || node->used_as_abstract_origin
        || has_analyzed_clone_p (node))
      {
@@@ -1214,8 -1214,8 +1214,8 @@@ compare_tree_sccs_1 (tree t1, tree t2, 
  
    if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
      {
 -      compare_values (TREE_INT_CST_LOW);
 -      compare_values (TREE_INT_CST_HIGH);
 +      if (!wi::eq_p (t1, t2))
 +      return false;
      }
  
    if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
@@@ -2398,9 -2398,9 +2398,9 @@@ cmp_partitions_order (const void *a, co
    int ordera = -1, orderb = -1;
  
    if (lto_symtab_encoder_size (pa->encoder))
-     ordera = lto_symtab_encoder_deref (pa->encoder, 0)->symbol.order;
+     ordera = lto_symtab_encoder_deref (pa->encoder, 0)->order;
    if (lto_symtab_encoder_size (pb->encoder))
-     orderb = lto_symtab_encoder_deref (pb->encoder, 0)->symbol.order;
+     orderb = lto_symtab_encoder_deref (pb->encoder, 0)->order;
    return orderb - ordera;
  }
  
@@@ -2479,14 -2479,14 +2479,14 @@@ lto_wpa_write_files (void
          for (lsei = lsei_start_in_partition (part->encoder); !lsei_end_p (lsei);
               lsei_next_in_partition (&lsei))
            {
-             symtab_node node = lsei_node (lsei);
+             symtab_node *node = lsei_node (lsei);
              fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name (node));
            }
          fprintf (cgraph_dump_file, "\n  Symbols in boundary: ");
          for (lsei = lsei_start (part->encoder); !lsei_end_p (lsei);
               lsei_next (&lsei))
            {
-             symtab_node node = lsei_node (lsei);
+             symtab_node *node = lsei_node (lsei);
              if (!lto_symtab_encoder_in_partition_p (part->encoder, node))
                {
                  fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name (node));
@@@ -2750,7 -2750,7 +2750,7 @@@ read_cgraph_and_symbols (unsigned nfile
    int count = 0;
    struct lto_file_decl_data **decl_data;
    void **res;
-   symtab_node snode;
+   symtab_node *snode;
  
    init_cgraph ();
  
  
    FOR_EACH_SYMBOL (snode)
      if (symtab_real_symbol_p (snode)
-       && snode->symbol.lto_file_data
-       && snode->symbol.lto_file_data->resolution_map
-       && (res = pointer_map_contains (snode->symbol.lto_file_data->resolution_map,
-                                       snode->symbol.decl)))
-       snode->symbol.resolution
+       && snode->lto_file_data
+       && snode->lto_file_data->resolution_map
+       && (res = pointer_map_contains (snode->lto_file_data->resolution_map,
+                                       snode->decl)))
+       snode->resolution
        = (enum ld_plugin_symbol_resolution)(size_t)*res;
    for (i = 0; all_file_decl_data[i]; i++)
      if (all_file_decl_data[i]->resolution_map)
@@@ -2979,7 -2979,7 +2979,7 @@@ materialize_cgraph (void
  
    FOR_EACH_FUNCTION (node)
      {
-       if (node->symbol.lto_file_data)
+       if (node->lto_file_data)
        {
          lto_materialize_function (node);
          lto_stats.num_input_cgraph_nodes++;
@@@ -3074,7 -3074,7 +3074,7 @@@ print_lto_report_1 (void
  static void
  do_whole_program_analysis (void)
  {
-   symtab_node node;
+   symtab_node *node;
  
    timevar_start (TV_PHASE_OPT_GEN);
  
    /* AUX pointers are used by partitioning code to bookkeep number of
       partitions symbol is in.  This is no longer needed.  */
    FOR_EACH_SYMBOL (node)
-     node->symbol.aux = NULL;
+     node->aux = NULL;
  
    lto_stats.num_cgraph_partitions += ltrans_partitions.length ();
    timevar_pop (TV_WHOPR_PARTITIONING);
@@@ -3288,7 -3288,7 +3288,7 @@@ lto_main (void
  
          /* Record the global variables.  */
          FOR_EACH_DEFINED_VARIABLE (vnode)
-           vec_safe_push (lto_global_var_decls, vnode->symbol.decl);
+           vec_safe_push (lto_global_var_decls, vnode->decl);
        }
      }
  
diff --combined gcc/machmode.def
index 9ca8b799e97b8a0b956cf261627536877a38f9ab,8c4cd73a33500c338f2cb052765002214a366377..c425e6ae70f7ea05f53bae8a74516242b9f553e6
@@@ -121,11 -121,11 +121,11 @@@ along with GCC; see the file COPYING3
        to FORMAT.  Use in an ARCH-modes.def to reset the format
        of one of the float modes defined in this file.
  
-      PARTIAL_INT_MODE (MODE);
+      PARTIAL_INT_MODE (MODE, PRECISION, NAME);
          declares a mode of class PARTIAL_INT with the same size as
-       MODE (which must be an INT mode).  The name of the new mode
-       is made by prefixing a P to the name MODE.  This statement
-       may grow a PRECISION argument in the future.
+       MODE (which must be an INT mode) and precision PREC.
+       Optionally, NAME is the new name of the mode.  NAME is the
+       name of the mode.
  
       VECTOR_MODE (CLASS, MODE, COUNT);
          Declare a vector mode whose component mode is MODE (of class
@@@ -229,9 -229,6 +229,9 @@@ UACCUM_MODE (USA, 4, 16, 16); /* 16.16 
  UACCUM_MODE (UDA, 8, 32, 32); /* 32.32 */
  UACCUM_MODE (UTA, 16, 64, 64); /* 64.64 */
  
 +/* Should be overridden by EXTRA_MODES_FILE if wrong.  */
 +#define MAX_BITS_PER_UNIT 8
 +
  /* Allow the target to specify additional modes of various kinds.  */
  #if HAVE_EXTRA_MODES
  # include EXTRA_MODES_FILE
diff --combined gcc/omp-low.c
index 6c24d3eeaabc24fea2624f7257bf66442e58d7c7,a5b92107a1d539a86f6a6c5ff3d9729523f6683c..ad0c609622b293cbfd3047b64887b6610bf3850d
@@@ -32,6 -32,14 +32,14 @@@ along with GCC; see the file COPYING3
  #include "tree-inline.h"
  #include "langhooks.h"
  #include "diagnostic-core.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-into-ssa.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "flags.h"
  #include "function.h"
@@@ -2273,8 -2281,8 +2281,8 @@@ check_omp_nesting_restrictions (gimple 
                        : "#pragma omp cancellation point");
              return false;
            }
 -        switch (host_integerp (gimple_call_arg (stmt, 0), 0)
 -                ? tree_low_cst (gimple_call_arg (stmt, 0), 0)
 +        switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
 +                ? tree_to_shwi (gimple_call_arg (stmt, 0))
                  : 0)
            {
            case 1:
@@@ -2510,7 -2518,9 +2518,7 @@@ scan_omp_1_op (tree *tp, int *walk_subt
              if (tem != TREE_TYPE (t))
                {
                  if (TREE_CODE (t) == INTEGER_CST)
 -                  *tp = build_int_cst_wide (tem,
 -                                            TREE_INT_CST_LOW (t),
 -                                            TREE_INT_CST_HIGH (t));
 +                  *tp = wide_int_to_tree (tem, t);
                  else
                    TREE_TYPE (t) = tem;
                }
@@@ -2907,7 -2917,7 +2915,7 @@@ lower_rec_simd_input_clauses (tree new_
                                    OMP_CLAUSE_SAFELEN);
          if (c
              && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
 -          max_vf = tree_low_cst (OMP_CLAUSE_SAFELEN_EXPR (c), 0);
 +          max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
        }
        if (max_vf > 1)
        {
@@@ -6722,11 -6732,12 +6730,11 @@@ expand_omp_simd (struct omp_region *reg
        else
        {
          safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
 -        if (!host_integerp (safelen, 1)
 -            || (unsigned HOST_WIDE_INT) tree_low_cst (safelen, 1)
 -               > INT_MAX)
 +        if (!tree_fits_uhwi_p (safelen)
 +            || tree_to_uhwi (safelen) > INT_MAX)
            loop->safelen = INT_MAX;
          else
 -          loop->safelen = tree_low_cst (safelen, 1);
 +          loop->safelen = tree_to_uhwi (safelen);
          if (loop->safelen == 1)
            loop->safelen = 0;
        }
@@@ -7630,7 -7641,7 +7638,7 @@@ expand_omp_atomic (struct omp_region *r
    HOST_WIDE_INT index;
  
    /* Make sure the type is one of the supported sizes.  */
 -  index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
 +  index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
    index = exact_log2 (index);
    if (index >= 0 && index <= 4)
      {
@@@ -8783,9 -8794,9 +8791,9 @@@ lower_omp_for_lastprivate (struct omp_f
  
    /* When possible, use a strict equality expression.  This can let VRP
       type optimizations deduce the value and remove a copy.  */
 -  if (host_integerp (fd->loop.step, 0))
 +  if (tree_fits_shwi_p (fd->loop.step))
      {
 -      HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
 +      HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
        if (step == 1 || step == -1)
        cond_code = EQ_EXPR;
      }
        /* Optimize: v = 0; is usually cheaper than v = some_other_constant.  */
        vinit = fd->loop.n1;
        if (cond_code == EQ_EXPR
 -        && host_integerp (fd->loop.n2, 0)
 +        && tree_fits_shwi_p (fd->loop.n2)
          && ! integer_zerop (fd->loop.n2))
        vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
        else
diff --combined gcc/optabs.c
index 2bd82b09f2f443aa2c95a1b3d62df96991edd1e1,3755670af84218003560873a235e2a8b556740c5..d6e49c9272c9fee6b91f63baf74b7dffc597b17d
@@@ -851,8 -851,7 +851,8 @@@ expand_subword_shift (enum machine_mod
    if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD)
      {
        carries = outof_input;
 -      tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
 +      tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD,
 +                                          op1_mode), op1_mode);
        tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
                                   0, true, methods);
      }
                              outof_input, const1_rtx, 0, unsignedp, methods);
        if (shift_mask == BITS_PER_WORD - 1)
        {
 -        tmp = immed_double_const (-1, -1, op1_mode);
 +        tmp = immed_wide_int_const 
 +          (wi::minus_one (GET_MODE_PRECISION (op1_mode)), op1_mode);
          tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp,
                                       0, true, methods);
        }
        else
        {
 -        tmp = immed_double_const (BITS_PER_WORD - 1, 0, op1_mode);
 +        tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD - 1,
 +                                              op1_mode), op1_mode);
          tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
                                       0, true, methods);
        }
@@@ -1038,7 -1035,7 +1038,7 @@@ expand_doubleword_shift (enum machine_m
       is true when the effective shift value is less than BITS_PER_WORD.
       Set SUPERWORD_OP1 to the shift count that should be used to shift
       OUTOF_INPUT into INTO_TARGET when the condition is false.  */
 -  tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
 +  tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD, op1_mode), op1_mode);
    if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1)
      {
        /* Set CMP1 to OP1 & BITS_PER_WORD.  The result is zero iff OP1
@@@ -2891,6 -2888,7 +2891,6 @@@ expand_absneg_bit (enum rtx_code code, 
    const struct real_format *fmt;
    int bitpos, word, nwords, i;
    enum machine_mode imode;
 -  double_int mask;
    rtx temp, insns;
  
    /* The format has to have a simple sign bit.  */
        nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
      }
  
 -  mask = double_int_zero.set_bit (bitpos);
 +  wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode));
    if (code == ABS)
      mask = ~mask;
  
            {
              temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
                                   op0_piece,
 -                                 immed_double_int_const (mask, imode),
 +                                 immed_wide_int_const (mask, imode),
                                   targ_piece, 1, OPTAB_LIB_WIDEN);
              if (temp != targ_piece)
                emit_move_insn (targ_piece, temp);
      {
        temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
                           gen_lowpart (imode, op0),
 -                         immed_double_int_const (mask, imode),
 +                         immed_wide_int_const (mask, imode),
                           gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
        target = lowpart_subreg_maybe_copy (mode, temp, imode);
  
@@@ -3567,6 -3565,8 +3567,6 @@@ expand_copysign_absneg (enum machine_mo
      }
    else
      {
 -      double_int mask;
 -
        if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
        {
          imode = int_mode_for_mode (mode);
          op1 = operand_subword_force (op1, word, mode);
        }
  
 -      mask = double_int_zero.set_bit (bitpos);
 -
 +      wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode));
        sign = expand_binop (imode, and_optab, op1,
 -                         immed_double_int_const (mask, imode),
 +                         immed_wide_int_const (mask, imode),
                           NULL_RTX, 1, OPTAB_LIB_WIDEN);
      }
  
@@@ -3633,6 -3634,7 +3633,6 @@@ expand_copysign_bit (enum machine_mode 
                     int bitpos, bool op0_is_abs)
  {
    enum machine_mode imode;
 -  double_int mask;
    int word, nwords, i;
    rtx temp, insns;
  
        nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
      }
  
 -  mask = double_int_zero.set_bit (bitpos);
 +  wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode));
  
    if (target == 0
        || target == op0
              if (!op0_is_abs)
                op0_piece
                  = expand_binop (imode, and_optab, op0_piece,
 -                                immed_double_int_const (~mask, imode),
 +                                immed_wide_int_const (~mask, imode),
                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
 -
              op1 = expand_binop (imode, and_optab,
                                  operand_subword_force (op1, i, mode),
 -                                immed_double_int_const (mask, imode),
 +                                immed_wide_int_const (mask, imode),
                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
  
              temp = expand_binop (imode, ior_optab, op0_piece, op1,
    else
      {
        op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1),
 -                        immed_double_int_const (mask, imode),
 +                        immed_wide_int_const (mask, imode),
                          NULL_RTX, 1, OPTAB_LIB_WIDEN);
  
        op0 = gen_lowpart (imode, op0);
        if (!op0_is_abs)
        op0 = expand_binop (imode, and_optab, op0,
 -                          immed_double_int_const (~mask, imode),
 +                          immed_wide_int_const (~mask, imode),
                            NULL_RTX, 1, OPTAB_LIB_WIDEN);
 -
        temp = expand_binop (imode, ior_optab, op0, op1,
                           gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
        target = lowpart_subreg_maybe_copy (mode, temp, imode);
@@@ -6620,8 -6624,8 +6620,8 @@@ expand_vec_perm (enum machine_mode mode
          icode = direct_optab_handler (vec_perm_const_optab, qimode);
          if (icode != CODE_FOR_nothing)
            {
-             tmp = expand_vec_perm_1 (icode, gen_lowpart (qimode, target),
-                                      gen_lowpart (qimode, v0),
+             tmp = mode != qimode ? gen_reg_rtx (qimode) : target;
+             tmp = expand_vec_perm_1 (icode, tmp, gen_lowpart (qimode, v0),
                                       gen_lowpart (qimode, v1), sel_qi);
              if (tmp)
                return gen_lowpart (mode, tmp);
        }
        tmp = gen_rtx_CONST_VECTOR (qimode, vec);
        sel = gen_lowpart (qimode, sel);
-       sel = expand_vec_perm (qimode, sel, sel, tmp, NULL);
+       sel = expand_vec_perm (qimode, gen_reg_rtx (qimode), sel, tmp, NULL);
        gcc_assert (sel != NULL);
  
        /* Add the byte offset to each byte element.  */
        gcc_assert (sel_qi != NULL);
      }
  
-   tmp = expand_vec_perm_1 (icode, gen_lowpart (qimode, target),
-                          gen_lowpart (qimode, v0),
+   tmp = mode != qimode ? gen_reg_rtx (qimode) : target;
+   tmp = expand_vec_perm_1 (icode, tmp, gen_lowpart (qimode, v0),
                           gen_lowpart (qimode, v1), sel_qi);
    if (tmp)
      tmp = gen_lowpart (mode, tmp);
@@@ -7036,8 -7040,7 +7036,7 @@@ maybe_emit_atomic_exchange (rtx target
  
        create_output_operand (&ops[0], target, mode);
        create_fixed_operand (&ops[1], mem);
-       /* VAL may have been promoted to a wider mode.  Shrink it if so.  */
-       create_convert_operand_to (&ops[2], val, mode, true);
+       create_input_operand (&ops[2], val, mode);
        create_integer_operand (&ops[3], model);
        if (maybe_expand_insn (icode, 4, ops))
        return ops[0].value;
@@@ -7076,8 -7079,7 +7075,7 @@@ maybe_emit_sync_lock_test_and_set (rtx 
        struct expand_operand ops[3];
        create_output_operand (&ops[0], target, mode);
        create_fixed_operand (&ops[1], mem);
-       /* VAL may have been promoted to a wider mode.  Shrink it if so.  */
-       create_convert_operand_to (&ops[2], val, mode, true);
+       create_input_operand (&ops[2], val, mode);
        if (maybe_expand_insn (icode, 3, ops))
        return ops[0].value;
      }
@@@ -7119,8 -7121,6 +7117,6 @@@ maybe_emit_compare_and_swap_exchange_lo
      {
        if (!target || !register_operand (target, mode))
        target = gen_reg_rtx (mode);
-       if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
-       val = convert_modes (mode, GET_MODE (val), val, 1);
        if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
        return target;
      }
@@@ -7332,8 -7332,8 +7328,8 @@@ expand_atomic_compare_and_swap (rtx *pt
        create_output_operand (&ops[0], target_bool, bool_mode);
        create_output_operand (&ops[1], target_oval, mode);
        create_fixed_operand (&ops[2], mem);
-       create_convert_operand_to (&ops[3], expected, mode, true);
-       create_convert_operand_to (&ops[4], desired, mode, true);
+       create_input_operand (&ops[3], expected, mode);
+       create_input_operand (&ops[4], desired, mode);
        create_integer_operand (&ops[5], is_weak);
        create_integer_operand (&ops[6], succ_model);
        create_integer_operand (&ops[7], fail_model);
  
        create_output_operand (&ops[0], target_oval, mode);
        create_fixed_operand (&ops[1], mem);
-       create_convert_operand_to (&ops[2], expected, mode, true);
-       create_convert_operand_to (&ops[3], desired, mode, true);
+       create_input_operand (&ops[2], expected, mode);
+       create_input_operand (&ops[3], desired, mode);
        if (!maybe_expand_insn (icode, 4, ops))
        return false;
  
diff --combined gcc/predict.c
index d17b9f21a40a8d3a14f6c348c19dd42f413eee77,cc9a0534e03dc4e21e9e0aa82fe02eb5e1e9cf7e..d164500d0c610feb5b1c07b366d1cdebcb02a2dd
@@@ -50,7 -50,14 +50,14 @@@ along with GCC; see the file COPYING3
  #include "params.h"
  #include "target.h"
  #include "cfgloop.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
  #include "ggc.h"
  #include "tree-pass.h"
  #include "tree-scalar-evolution.h"
@@@ -1045,15 -1052,15 +1052,15 @@@ strips_small_constant (tree t1, tree t2
      return NULL;
    else if (TREE_CODE (t1) == SSA_NAME)
      ret = t1;
 -  else if (host_integerp (t1, 0))
 -    value = tree_low_cst (t1, 0);
 +  else if (tree_fits_shwi_p (t1))
 +    value = tree_to_shwi (t1);
    else
      return NULL;
  
    if (!t2)
      return ret;
 -  else if (host_integerp (t2, 0))
 -    value = tree_low_cst (t2, 0);
 +  else if (tree_fits_shwi_p (t2))
 +    value = tree_to_shwi (t2);
    else if (TREE_CODE (t2) == SSA_NAME)
      {
        if (ret)
@@@ -1149,7 -1156,7 +1156,7 @@@ is_comparison_with_loop_invariant_p (gi
        code = invert_tree_comparison (code, false);
        bound = iv0.base;
        base = iv1.base;
 -      if (host_integerp (iv1.step, 0))
 +      if (tree_fits_shwi_p (iv1.step))
        step = iv1.step;
        else
        return false;
      {
        bound = iv1.base;
        base = iv0.base;
 -      if (host_integerp (iv0.step, 0))
 +      if (tree_fits_shwi_p (iv0.step))
        step = iv0.step;
        else
        return false;
@@@ -1292,63 -1299,81 +1299,63 @@@ predict_iv_comparison (struct loop *loo
  
    /* If loop bound, base and compare bound are all constants, we can
       calculate the probability directly.  */
 -  if (host_integerp (loop_bound_var, 0)
 -      && host_integerp (compare_var, 0)
 -      && host_integerp (compare_base, 0))
 +  if (tree_fits_shwi_p (loop_bound_var)
 +      && tree_fits_shwi_p (compare_var)
 +      && tree_fits_shwi_p (compare_base))
      {
        int probability;
 -      bool of, overflow = false;
 -      double_int mod, compare_count, tem, loop_count;
 +      bool overflow, overall_overflow = false;
 +      widest_int compare_count, tem;
  
 -      double_int loop_bound = tree_to_double_int (loop_bound_var);
 -      double_int compare_bound = tree_to_double_int (compare_var);
 -      double_int base = tree_to_double_int (compare_base);
 -      double_int compare_step = tree_to_double_int (compare_step_var);
 +      widest_int loop_bound = wi::to_widest (loop_bound_var);
 +      widest_int compare_bound = wi::to_widest (compare_var);
 +      widest_int base = wi::to_widest (compare_base);
 +      widest_int compare_step = wi::to_widest (compare_step_var);
  
        /* (loop_bound - base) / compare_step */
 -      tem = loop_bound.sub_with_overflow (base, &of);
 -      overflow |= of;
 -      loop_count = tem.divmod_with_overflow (compare_step,
 -                                            0, TRUNC_DIV_EXPR,
 -                                            &mod, &of);
 -      overflow |= of;
 -
 -      if ((!compare_step.is_negative ())
 +      tem = wi::sub (loop_bound, base, SIGNED, &overflow);
 +      overall_overflow |= overflow;
 +      widest_int loop_count = wi::div_trunc (tem, compare_step, SIGNED,
 +                                           &overflow);
 +      overall_overflow |= overflow;
 +
 +      if (!wi::neg_p (compare_step)
            ^ (compare_code == LT_EXPR || compare_code == LE_EXPR))
        {
          /* (loop_bound - compare_bound) / compare_step */
 -        tem = loop_bound.sub_with_overflow (compare_bound, &of);
 -        overflow |= of;
 -        compare_count = tem.divmod_with_overflow (compare_step,
 -                                                   0, TRUNC_DIV_EXPR,
 -                                                   &mod, &of);
 -        overflow |= of;
 +        tem = wi::sub (loop_bound, compare_bound, SIGNED, &overflow);
 +        overall_overflow |= overflow;
 +        compare_count = wi::div_trunc (tem, compare_step, SIGNED, &overflow);
 +        overall_overflow |= overflow;
        }
        else
          {
          /* (compare_bound - base) / compare_step */
 -        tem = compare_bound.sub_with_overflow (base, &of);
 -        overflow |= of;
 -          compare_count = tem.divmod_with_overflow (compare_step,
 -                                                   0, TRUNC_DIV_EXPR,
 -                                                   &mod, &of);
 -        overflow |= of;
 +        tem = wi::sub (compare_bound, base, SIGNED, &overflow);
 +        overall_overflow |= overflow;
 +          compare_count = wi::div_trunc (tem, compare_step, SIGNED, &overflow);
 +        overall_overflow |= overflow;
        }
        if (compare_code == LE_EXPR || compare_code == GE_EXPR)
        ++compare_count;
        if (loop_bound_code == LE_EXPR || loop_bound_code == GE_EXPR)
        ++loop_count;
 -      if (compare_count.is_negative ())
 -        compare_count = double_int_zero;
 -      if (loop_count.is_negative ())
 -        loop_count = double_int_zero;
 -      if (loop_count.is_zero ())
 +      if (wi::neg_p (compare_count))
 +        compare_count = 0;
 +      if (wi::neg_p (loop_count))
 +        loop_count = 0;
 +      if (loop_count == 0)
        probability = 0;
 -      else if (compare_count.scmp (loop_count) == 1)
 +      else if (wi::cmps (compare_count, loop_count) == 1)
        probability = REG_BR_PROB_BASE;
        else
          {
 -        /* If loop_count is too big, such that REG_BR_PROB_BASE * loop_count
 -           could overflow, shift both loop_count and compare_count right
 -           a bit so that it doesn't overflow.  Note both counts are known not
 -           to be negative at this point.  */
 -        int clz_bits = clz_hwi (loop_count.high);
 -        gcc_assert (REG_BR_PROB_BASE < 32768);
 -        if (clz_bits < 16)
 -          {
 -            loop_count.arshift (16 - clz_bits, HOST_BITS_PER_DOUBLE_INT);
 -            compare_count.arshift (16 - clz_bits, HOST_BITS_PER_DOUBLE_INT);
 -          }
 -        tem = compare_count.mul_with_sign (double_int::from_shwi
 -                                          (REG_BR_PROB_BASE), true, &of);
 -        gcc_assert (!of);
 -        tem = tem.divmod (loop_count, true, TRUNC_DIV_EXPR, &mod);
 +        tem = compare_count * REG_BR_PROB_BASE;
 +        tem = wi::udiv_trunc (tem, loop_count);
          probability = tem.to_uhwi ();
        }
  
 -      if (!overflow)
 +      if (!overall_overflow)
          predict_edge (then_edge, PRED_LOOP_IV_COMPARE, probability);
  
        return;
@@@ -1531,10 -1556,10 +1538,10 @@@ predict_loops (void
  
          if (TREE_CODE (niter) == INTEGER_CST)
            {
 -            if (host_integerp (niter, 1)
 +            if (tree_fits_uhwi_p (niter)
                  && max
                  && compare_tree_int (niter, max - 1) == -1)
 -              nitercst = tree_low_cst (niter, 1) + 1;
 +              nitercst = tree_to_uhwi (niter) + 1;
              else
                nitercst = max;
              predictor = PRED_LOOP_ITERATIONS;
          if (loop_bound_var)
            predict_iv_comparison (loop, bb, loop_bound_var, loop_iv_base,
                                   loop_bound_code,
 -                                 tree_low_cst (loop_bound_step, 0));
 +                                 tree_to_shwi (loop_bound_step));
        }
  
        /* Free basic blocks from get_loop_body.  */
diff --combined gcc/print-tree.c
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.  */
@@@ -122,7 -122,16 +123,7 @@@ print_node_brief (FILE *file, const cha
        fprintf (file, " overflow");
  
        fprintf (file, " ");
 -      if (TREE_INT_CST_HIGH (node) == 0)
 -      fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, TREE_INT_CST_LOW (node));
 -      else if (TREE_INT_CST_HIGH (node) == -1
 -             && TREE_INT_CST_LOW (node) != 0)
 -      fprintf (file, "-" HOST_WIDE_INT_PRINT_UNSIGNED,
 -               -TREE_INT_CST_LOW (node));
 -      else
 -      fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
 -               (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (node),
 -               (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (node));
 +      print_dec (node, file, TYPE_SIGN (TREE_TYPE (node)));
      }
    if (TREE_CODE (node) == REAL_CST)
      {
@@@ -327,7 -336,7 +328,7 @@@ print_node (FILE *file, const char *pre
    if (TREE_VISITED (node))
      fputs (" visited", file);
  
 -  if (code != TREE_VEC && code != SSA_NAME)
 +  if (code != TREE_VEC && code != INTEGER_CST && code != SSA_NAME)
      {
        if (TREE_LANG_FLAG_0 (node))
        fputs (" tree_0", file);
            fprintf (file, " overflow");
  
          fprintf (file, " ");
 -        if (TREE_INT_CST_HIGH (node) == 0)
 -          fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED,
 -                   TREE_INT_CST_LOW (node));
 -        else if (TREE_INT_CST_HIGH (node) == -1
 -                 && TREE_INT_CST_LOW (node) != 0)
 -          fprintf (file, "-" HOST_WIDE_INT_PRINT_UNSIGNED,
 -                   -TREE_INT_CST_LOW (node));
 -        else
 -          fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
 -                   (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (node),
 -                   (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (node));
 +        print_dec (node, file, TYPE_SIGN (TREE_TYPE (node)));
          break;
  
        case REAL_CST:
diff --combined gcc/recog.c
index e4f4fadfd86628cc4319f37f804e6ab260f5bfc4,c8594bb59044577d67adc655264b5bd4ceade272..821ce267edec13da4a75380e35162a5bc95ad5e4
@@@ -22,6 -22,7 +22,7 @@@ along with GCC; see the file COPYING3
  #include "system.h"
  #include "coretypes.h"
  #include "tm.h"
+ #include "tree.h"
  #include "rtl-error.h"
  #include "tm_p.h"
  #include "insn-config.h"
@@@ -725,7 -726,7 +726,7 @@@ validate_replace_rtx_1 (rtx *loc, rtx f
    /* Call ourself recursively to perform the replacements.
       We must not replace inside already replaced expression, otherwise we
       get infinite recursion for replacements like (reg X)->(subreg (reg X))
-      done by regmove, so we must special case shared ASM_OPERANDS.  */
+      so we must special case shared ASM_OPERANDS.  */
  
    if (GET_CODE (x) == PARALLEL)
      {
    if (num_changes == prev_changes)
      return;
  
+   /* ??? The regmove is no more, so is this aberration still necessary?  */
    /* Allow substituted expression to have different mode.  This is used by
       regmove to change mode of pseudo register.  */
    if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
@@@ -1148,7 -1150,7 +1150,7 @@@ immediate_operand (rtx op, enum machine
                                            : mode, op));
  }
  
 -/* Returns 1 if OP is an operand that is a CONST_INT.  */
 +/* Returns 1 if OP is an operand that is a CONST_INT of mode MODE.  */
  
  int
  const_int_operand (rtx op, enum machine_mode mode)
    return 1;
  }
  
 +#if TARGET_SUPPORTS_WIDE_INT
 +/* Returns 1 if OP is an operand that is a CONST_INT or CONST_WIDE_INT
 +   of mode MODE.  */
 +int
 +const_scalar_int_operand (rtx op, enum machine_mode mode)
 +{
 +  if (!CONST_SCALAR_INT_P (op))
 +    return 0;
 +
 +  if (CONST_INT_P (op))
 +    return const_int_operand (op, mode);
 +
 +  if (mode != VOIDmode)
 +    {
 +      int prec = GET_MODE_PRECISION (mode);
 +      int bitsize = GET_MODE_BITSIZE (mode);
 +      
 +      if (CONST_WIDE_INT_NUNITS (op) * HOST_BITS_PER_WIDE_INT > bitsize)
 +      return 0;
 +      
 +      if (prec == bitsize)
 +      return 1;
 +      else
 +      {
 +        /* Multiword partial int.  */
 +        HOST_WIDE_INT x 
 +          = CONST_WIDE_INT_ELT (op, CONST_WIDE_INT_NUNITS (op) - 1);
 +        return (sext_hwi (x, prec & (HOST_BITS_PER_WIDE_INT - 1)) == x);
 +      }
 +    }
 +  return 1;
 +}
 +
 +/* Returns 1 if OP is an operand that is a CONST_WIDE_INT of mode
 +   MODE.  This most likely is not as useful as
 +   const_scalar_int_operand since it does not accept CONST_INTs, but
 +   is here for consistancy.  */
 +int
 +const_wide_int_operand (rtx op, enum machine_mode mode)
 +{
 +  if (!CONST_WIDE_INT_P (op))
 +    return 0;
 +
 +  return const_scalar_int_operand (op, mode);
 +}
 +
  /* Returns 1 if OP is an operand that is a constant integer or constant
 -   floating-point number.  */
 +   floating-point number of MODE.  */
 +
 +int
 +const_double_operand (rtx op, enum machine_mode mode)
 +{
 +  return (GET_CODE (op) == CONST_DOUBLE)
 +        && (GET_MODE (op) == mode || mode == VOIDmode);
 +}
 +#else
 +/* Returns 1 if OP is an operand that is a constant integer or constant
 +   floating-point number of MODE.  */
  
  int
  const_double_operand (rtx op, enum machine_mode mode)
          && (mode == VOIDmode || GET_MODE (op) == mode
              || GET_MODE (op) == VOIDmode));
  }
 -
 -/* Return 1 if OP is a general operand that is not an immediate operand.  */
 +#endif
 +/* Return 1 if OP is a general operand that is not an immediate
 +   operand of mode MODE.  */
  
  int
  nonimmediate_operand (rtx op, enum machine_mode mode)
    return (general_operand (op, mode) && ! CONSTANT_P (op));
  }
  
 -/* Return 1 if OP is a register reference or immediate value of mode MODE.  */
 +/* Return 1 if OP is a register reference or immediate value of mode
 +   MODE.  */
  
  int
  nonmemory_operand (rtx op, enum machine_mode mode)
@@@ -3126,6 -3070,9 +3128,9 @@@ peep2_reg_dead_p (int ofs, rtx reg
    return 1;
  }
  
+ /* Regno offset to be used in the register search.  */
+ static int search_ofs;
  /* Try to find a hard register of mode MODE, matching the register class in
     CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
     remains available until the end of LAST_INSN.  LAST_INSN may be NULL_RTX,
@@@ -3141,7 -3088,6 +3146,6 @@@ rt
  peep2_find_free_register (int from, int to, const char *class_str,
                          enum machine_mode mode, HARD_REG_SET *reg_set)
  {
-   static int search_ofs;
    enum reg_class cl;
    HARD_REG_SET live;
    df_ref *def_rec;
@@@ -3606,6 -3552,7 +3610,7 @@@ peephole2_optimize (void
    /* Initialize the regsets we're going to use.  */
    for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
      peep2_insn_data[i].live_before = BITMAP_ALLOC (&reg_obstack);
+   search_ofs = 0;
    live = BITMAP_ALLOC (&reg_obstack);
  
    FOR_EACH_BB_REVERSE (bb)
diff --combined gcc/stor-layout.c
index eed3b22e8df85e312c20956dda6a81b428fbc6a9,f390eea79105c714c85d0fb611247b96fd2ce74f..ef5d74087cce1ecb30b0941cb35665892b989ae8
@@@ -331,9 -331,9 +331,9 @@@ mode_for_size_tree (const_tree size, en
    unsigned HOST_WIDE_INT uhwi;
    unsigned int ui;
  
 -  if (!host_integerp (size, 1))
 +  if (!tree_fits_uhwi_p (size))
      return BLKmode;
 -  uhwi = tree_low_cst (size, 1);
 +  uhwi = tree_to_uhwi (size);
    ui = uhwi;
    if (uhwi != ui)
      return BLKmode;
@@@ -383,6 -383,7 +383,7 @@@ int_mode_for_mode (enum machine_mode mo
      case MODE_VECTOR_ACCUM:
      case MODE_VECTOR_UFRACT:
      case MODE_VECTOR_UACCUM:
+     case MODE_POINTER_BOUNDS:
        mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
        break;
  
@@@ -481,10 -482,10 +482,10 @@@ mode_for_array (tree elem_type, tree si
      return TYPE_MODE (elem_type);
  
    limit_p = true;
 -  if (host_integerp (size, 1) && host_integerp (elem_size, 1))
 +  if (tree_fits_uhwi_p (size) && tree_fits_uhwi_p (elem_size))
      {
 -      int_size = tree_low_cst (size, 1);
 -      int_elem_size = tree_low_cst (elem_size, 1);
 +      int_size = tree_to_uhwi (size);
 +      int_elem_size = tree_to_uhwi (elem_size);
        if (int_elem_size > 0
          && int_size % int_elem_size == 0
          && targetm.array_mode_supported_p (TYPE_MODE (elem_type),
@@@ -606,14 -607,10 +607,10 @@@ layout_decl (tree decl, unsigned int kn
  
          /* See if we can use an ordinary integer mode for a bit-field.
             Conditions are: a fixed size that is correct for another mode,
-            occupying a complete byte or bytes on proper boundary,
-            and not -fstrict-volatile-bitfields.  If the latter is set,
-            we unfortunately can't check TREE_THIS_VOLATILE, as a cast
-            may make a volatile object later.  */
+            occupying a complete byte or bytes on proper boundary.  */
          if (TYPE_SIZE (type) != 0
              && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
-             && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
-             && flag_strict_volatile_bitfields <= 0)
+             && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
            {
              enum machine_mode xmode
                = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
        if (size != 0 && TREE_CODE (size) == INTEGER_CST
          && compare_tree_int (size, larger_than_size) > 0)
        {
 -        int size_as_int = TREE_INT_CST_LOW (size);
 +        int size_as_int = tree_to_hwi (size);
  
          if (compare_tree_int (size, size_as_int) == 0)
            warning (OPT_Wlarger_than_, "size of %q+D is %d bytes", decl, size_as_int);
@@@ -1055,7 -1052,7 +1052,7 @@@ excess_unit_span (HOST_WIDE_INT byte_of
  
    offset = offset % align;
    return ((offset + size + align - 1) / align
 -        > ((unsigned HOST_WIDE_INT) tree_low_cst (TYPE_SIZE (type), 1)
 +        > ((unsigned HOST_WIDE_INT) tree_to_uhwi (TYPE_SIZE (type))
             / align));
  }
  #endif
@@@ -1115,14 -1112,14 +1112,14 @@@ place_field (record_layout_info rli, tr
    /* Work out the known alignment so far.  Note that A & (-A) is the
       value of the least-significant bit in A that is one.  */
    if (! integer_zerop (rli->bitpos))
 -    known_align = (tree_low_cst (rli->bitpos, 1)
 -                 & - tree_low_cst (rli->bitpos, 1));
 +    known_align = (tree_to_uhwi (rli->bitpos)
 +                 & - tree_to_uhwi (rli->bitpos));
    else if (integer_zerop (rli->offset))
      known_align = 0;
 -  else if (host_integerp (rli->offset, 1))
 +  else if (tree_fits_uhwi_p (rli->offset))
      known_align = (BITS_PER_UNIT
 -                 * (tree_low_cst (rli->offset, 1)
 -                    & - tree_low_cst (rli->offset, 1)));
 +                 * (tree_to_uhwi (rli->offset)
 +                    & - tree_to_uhwi (rli->offset)));
    else
      known_align = rli->offset_align;
  
          || TYPE_ALIGN (type) <= BITS_PER_UNIT)
        && maximum_field_alignment == 0
        && ! integer_zerop (DECL_SIZE (field))
 -      && host_integerp (DECL_SIZE (field), 1)
 -      && host_integerp (rli->offset, 1)
 -      && host_integerp (TYPE_SIZE (type), 1))
 +      && tree_fits_uhwi_p (DECL_SIZE (field))
 +      /* BUG!!! rli->offset is checked as unsigned but used as signed.   */
 +      && tree_fits_uhwi_p (rli->offset)
 +      && tree_fits_uhwi_p (TYPE_SIZE (type)))
      {
        unsigned int type_align = TYPE_ALIGN (type);
        tree dsize = DECL_SIZE (field);
 -      HOST_WIDE_INT field_size = tree_low_cst (dsize, 1);
 -      HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
 -      HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
 +      HOST_WIDE_INT field_size = tree_to_uhwi (dsize);
 +      HOST_WIDE_INT offset = tree_to_shwi (rli->offset);
 +      HOST_WIDE_INT bit_offset = tree_to_shwi (rli->bitpos);
  
  #ifdef ADJUST_FIELD_ALIGN
        if (! TYPE_USER_ALIGN (type))
        && DECL_BIT_FIELD_TYPE (field)
        && ! DECL_PACKED (field)
        && ! integer_zerop (DECL_SIZE (field))
 -      && host_integerp (DECL_SIZE (field), 1)
 -      && host_integerp (rli->offset, 1)
 -      && host_integerp (TYPE_SIZE (type), 1))
 +      && tree_fits_uhwi_p (DECL_SIZE (field))
 +      /* BUG!!! rli->offset is checked as unsigned but used as signed.   */
 +      && tree_fits_shwi_p (rli->offset)
 +      && tree_fits_uhwi_p (TYPE_SIZE (type)))
      {
        unsigned int type_align = TYPE_ALIGN (type);
        tree dsize = DECL_SIZE (field);
 -      HOST_WIDE_INT field_size = tree_low_cst (dsize, 1);
 -      HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
 -      HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
 +      HOST_WIDE_INT field_size = tree_to_uhwi (dsize);
 +      HOST_WIDE_INT offset = tree_to_shwi (rli->offset);
 +      HOST_WIDE_INT bit_offset = tree_to_shwi (rli->bitpos);
  
  #ifdef ADJUST_FIELD_ALIGN
        if (! TYPE_USER_ALIGN (type))
          if (DECL_BIT_FIELD_TYPE (field)
              && !integer_zerop (DECL_SIZE (field))
              && !integer_zerop (DECL_SIZE (rli->prev_field))
 -            && host_integerp (DECL_SIZE (rli->prev_field), 0)
 -            && host_integerp (TYPE_SIZE (type), 0)
 +            && tree_fits_shwi_p (DECL_SIZE (rli->prev_field))
 +            /* BUG!!! TYPE_SIZE (type) is checked as unsigned but used as signed.   */
 +            && tree_fits_shwi_p (TYPE_SIZE (type))
              && simple_cst_equal (TYPE_SIZE (type), TYPE_SIZE (prev_type)))
            {
              /* We're in the middle of a run of equal type size fields; make
                 sure we realign if we run out of bits.  (Not decl size,
                 type size!) */
 -            HOST_WIDE_INT bitsize = tree_low_cst (DECL_SIZE (field), 1);
 +            HOST_WIDE_INT bitsize = tree_to_uhwi (DECL_SIZE (field));
  
              if (rli->remaining_in_alignment < bitsize)
                {
 -                HOST_WIDE_INT typesize = tree_low_cst (TYPE_SIZE (type), 1);
 +                HOST_WIDE_INT typesize = tree_to_uhwi (TYPE_SIZE (type));
  
                  /* out of bits; bump up to next 'word'.  */
                  rli->bitpos
             until we see a bitfield (and come by here again) we just skip
             calculating it.  */
          if (DECL_SIZE (field) != NULL
 -            && host_integerp (TYPE_SIZE (TREE_TYPE (field)), 1)
 -            && host_integerp (DECL_SIZE (field), 1))
 +            && tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (field)))
 +            && tree_fits_uhwi_p (DECL_SIZE (field)))
            {
              unsigned HOST_WIDE_INT bitsize
 -              = tree_low_cst (DECL_SIZE (field), 1);
 +              = tree_to_uhwi (DECL_SIZE (field));
              unsigned HOST_WIDE_INT typesize
 -              = tree_low_cst (TYPE_SIZE (TREE_TYPE (field)), 1);
 +              = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (field)));
  
              if (typesize < bitsize)
                rli->remaining_in_alignment = 0;
       approximate this by seeing if its position changed), lay out the field
       again; perhaps we can use an integral mode for it now.  */
    if (! integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
 -    actual_align = (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
 -                  & - tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1));
 +    actual_align = (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
 +                  & - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)));
    else if (integer_zerop (DECL_FIELD_OFFSET (field)))
      actual_align = MAX (BIGGEST_ALIGNMENT, rli->record_align);
 -  else if (host_integerp (DECL_FIELD_OFFSET (field), 1))
 +  else if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)))
      actual_align = (BITS_PER_UNIT
 -                 * (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
 -                    & - tree_low_cst (DECL_FIELD_OFFSET (field), 1)));
 +                 * (tree_to_uhwi (DECL_FIELD_OFFSET (field))
 +                    & - tree_to_uhwi (DECL_FIELD_OFFSET (field))));
    else
      actual_align = DECL_OFFSET_ALIGN (field);
    /* ACTUAL_ALIGN is still the actual alignment *within the record* .
@@@ -1589,7 -1583,7 +1586,7 @@@ compute_record_mode (tree type
       line.  */
    SET_TYPE_MODE (type, BLKmode);
  
 -  if (! host_integerp (TYPE_SIZE (type), 1))
 +  if (! tree_fits_uhwi_p (TYPE_SIZE (type)))
      return;
  
    /* A record which has any BLKmode members must itself be
              && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field))
              && !(TYPE_SIZE (TREE_TYPE (field)) != 0
                   && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))))
 -        || ! host_integerp (bit_position (field), 1)
 +        || ! tree_fits_uhwi_p (bit_position (field))
          || DECL_SIZE (field) == 0
 -        || ! host_integerp (DECL_SIZE (field), 1))
 +        || ! tree_fits_uhwi_p (DECL_SIZE (field)))
        return;
  
        /* If this field is the whole struct, remember its mode so
       matches the type's size.  This only applies to RECORD_TYPE.  This
       does not apply to unions.  */
    if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode
 -      && host_integerp (TYPE_SIZE (type), 1)
 -      && GET_MODE_BITSIZE (mode) == TREE_INT_CST_LOW (TYPE_SIZE (type)))
 +      && tree_fits_uhwi_p (TYPE_SIZE (type))
 +      && GET_MODE_BITSIZE (mode) == tree_to_uhwi (TYPE_SIZE (type)))
      SET_TYPE_MODE (type, mode);
    else
      SET_TYPE_MODE (type, mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1));
@@@ -1768,11 -1762,11 +1765,11 @@@ finish_bitfield_representative (tree re
  
    size = size_diffop (DECL_FIELD_OFFSET (field),
                      DECL_FIELD_OFFSET (repr));
 -  gcc_assert (host_integerp (size, 1));
 -  bitsize = (tree_low_cst (size, 1) * BITS_PER_UNIT
 -           + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
 -           - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)
 -           + tree_low_cst (DECL_SIZE (field), 1));
 +  gcc_assert (tree_fits_uhwi_p (size));
 +  bitsize = (tree_to_uhwi (size) * BITS_PER_UNIT
 +           + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
 +           - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr))
 +           + tree_to_uhwi (DECL_SIZE (field)));
  
    /* Round up bitsize to multiples of BITS_PER_UNIT.  */
    bitsize = (bitsize + BITS_PER_UNIT - 1) & ~(BITS_PER_UNIT - 1);
        return;
        maxsize = size_diffop (DECL_FIELD_OFFSET (nextf),
                             DECL_FIELD_OFFSET (repr));
 -      if (host_integerp (maxsize, 1))
 +      if (tree_fits_uhwi_p (maxsize))
        {
 -        maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT
 -                      + tree_low_cst (DECL_FIELD_BIT_OFFSET (nextf), 1)
 -                      - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
 +        maxbitsize = (tree_to_uhwi (maxsize) * BITS_PER_UNIT
 +                      + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (nextf))
 +                      - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
          /* If the group ends within a bitfield nextf does not need to be
             aligned to BITS_PER_UNIT.  Thus round up.  */
          maxbitsize = (maxbitsize + BITS_PER_UNIT - 1) & ~(BITS_PER_UNIT - 1);
         use bitsize as fallback for this case.  */
        tree maxsize = size_diffop (TYPE_SIZE_UNIT (DECL_CONTEXT (field)),
                                  DECL_FIELD_OFFSET (repr));
 -      if (host_integerp (maxsize, 1))
 -      maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT
 -                    - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
 +      if (tree_fits_uhwi_p (maxsize))
 +      maxbitsize = (tree_to_uhwi (maxsize) * BITS_PER_UNIT
 +                    - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
        else
        maxbitsize = bitsize;
      }
@@@ -1924,8 -1918,8 +1921,8 @@@ finish_bitfield_layout (record_layout_i
             representative to be generated.  That will at most
             generate worse code but still maintain correctness with
             respect to the C++ memory model.  */
 -        else if (!((host_integerp (DECL_FIELD_OFFSET (repr), 1)
 -                    && host_integerp (DECL_FIELD_OFFSET (field), 1))
 +        else if (!((tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr))
 +                    && tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)))
                     || operand_equal_p (DECL_FIELD_OFFSET (repr),
                                         DECL_FIELD_OFFSET (field), 0)))
            {
@@@ -2128,6 -2122,14 +2125,14 @@@ layout_type (tree type
        TYPE_USER_ALIGN (type) = 0;
        SET_TYPE_MODE (type, VOIDmode);
        break;
+     case POINTER_BOUNDS_TYPE:
+       SET_TYPE_MODE (type,
+                      mode_for_size (TYPE_PRECISION (type),
+                                   MODE_POINTER_BOUNDS, 0));
+       TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
+       break;
  
      case OFFSET_TYPE:
        TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
                    && TYPE_UNSIGNED (TREE_TYPE (lb))
                    && tree_int_cst_lt (ub, lb))
                  {
 -                  unsigned prec = TYPE_PRECISION (TREE_TYPE (lb));
 -                  lb = double_int_to_tree
 -                         (ssizetype,
 -                          tree_to_double_int (lb).sext (prec));
 -                  ub = double_int_to_tree
 -                         (ssizetype,
 -                          tree_to_double_int (ub).sext (prec));
 +                  lb = wide_int_to_tree (ssizetype,
 +                                         offset_int::from (lb, SIGNED));
 +                  ub = wide_int_to_tree (ssizetype,
 +                                         offset_int::from (ub, SIGNED));
                  }
                length
                  = fold_convert (sizetype,
@@@ -2477,14 -2482,16 +2482,14 @@@ initialize_sizetypes (void
    TYPE_ALIGN (sizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (sizetype));
    TYPE_SIZE (sizetype) = bitsize_int (precision);
    TYPE_SIZE_UNIT (sizetype) = size_int (GET_MODE_SIZE (TYPE_MODE (sizetype)));
 -  set_min_and_max_values_for_integral_type (sizetype, precision,
 -                                          /*is_unsigned=*/true);
 +  set_min_and_max_values_for_integral_type (sizetype, precision, UNSIGNED);
  
    SET_TYPE_MODE (bitsizetype, smallest_mode_for_size (bprecision, MODE_INT));
    TYPE_ALIGN (bitsizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (bitsizetype));
    TYPE_SIZE (bitsizetype) = bitsize_int (bprecision);
    TYPE_SIZE_UNIT (bitsizetype)
      = size_int (GET_MODE_SIZE (TYPE_MODE (bitsizetype)));
 -  set_min_and_max_values_for_integral_type (bitsizetype, bprecision,
 -                                          /*is_unsigned=*/true);
 +  set_min_and_max_values_for_integral_type (bitsizetype, bprecision, UNSIGNED);
  
    /* Create the signed variants of *sizetype.  */
    ssizetype = make_signed_type (TYPE_PRECISION (sizetype));
  void
  set_min_and_max_values_for_integral_type (tree type,
                                          int precision,
 -                                        bool is_unsigned)
 +                                        signop sgn)
  {
 -  tree min_value;
 -  tree max_value;
 -
    /* For bitfields with zero width we end up creating integer types
       with zero precision.  Don't assign any minimum/maximum values
       to those types, they don't have any valid value.  */
    if (precision < 1)
      return;
  
 -  if (is_unsigned)
 -    {
 -      min_value = build_int_cst (type, 0);
 -      max_value
 -      = build_int_cst_wide (type, precision - HOST_BITS_PER_WIDE_INT >= 0
 -                            ? -1
 -                            : ((HOST_WIDE_INT) 1 << precision) - 1,
 -                            precision - HOST_BITS_PER_WIDE_INT > 0
 -                            ? ((unsigned HOST_WIDE_INT) ~0
 -                               >> (HOST_BITS_PER_WIDE_INT
 -                                   - (precision - HOST_BITS_PER_WIDE_INT)))
 -                            : 0);
 -    }
 -  else
 -    {
 -      min_value
 -      = build_int_cst_wide (type,
 -                            (precision - HOST_BITS_PER_WIDE_INT > 0
 -                             ? 0
 -                             : (HOST_WIDE_INT) (-1) << (precision - 1)),
 -                            (((HOST_WIDE_INT) (-1)
 -                              << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
 -                                  ? precision - HOST_BITS_PER_WIDE_INT - 1
 -                                  : 0))));
 -      max_value
 -      = build_int_cst_wide (type,
 -                            (precision - HOST_BITS_PER_WIDE_INT > 0
 -                             ? -1
 -                             : (HOST_WIDE_INT)
 -                               (((unsigned HOST_WIDE_INT) 1
 -                                 << (precision - 1)) - 1)),
 -                            (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
 -                             ? (HOST_WIDE_INT)
 -                               ((((unsigned HOST_WIDE_INT) 1
 -                                  << (precision - HOST_BITS_PER_WIDE_INT
 -                                      - 1))) - 1)
 -                             : 0));
 -    }
 -
 -  TYPE_MIN_VALUE (type) = min_value;
 -  TYPE_MAX_VALUE (type) = max_value;
 +  TYPE_MIN_VALUE (type)
 +    = wide_int_to_tree (type, wi::min_value (precision, sgn));
 +  TYPE_MAX_VALUE (type)
 +    = wide_int_to_tree (type, wi::max_value (precision, sgn));
  }
  
  /* Set the extreme values of TYPE based on its precision in bits,
@@@ -2528,7 -2575,14 +2533,7 @@@ fixup_signed_type (tree type
  {
    int precision = TYPE_PRECISION (type);
  
 -  /* We can not represent properly constants greater then
 -     HOST_BITS_PER_DOUBLE_INT, still we need the types
 -     as they are used by i386 vector extensions and friends.  */
 -  if (precision > HOST_BITS_PER_DOUBLE_INT)
 -    precision = HOST_BITS_PER_DOUBLE_INT;
 -
 -  set_min_and_max_values_for_integral_type (type, precision,
 -                                          /*is_unsigned=*/false);
 +  set_min_and_max_values_for_integral_type (type, precision, SIGNED);
  
    /* Lay out the type: set its alignment, size, etc.  */
    layout_type (type);
@@@ -2543,9 -2597,16 +2548,9 @@@ fixup_unsigned_type (tree type
  {
    int precision = TYPE_PRECISION (type);
  
 -  /* We can not represent properly constants greater then
 -     HOST_BITS_PER_DOUBLE_INT, still we need the types
 -     as they are used by i386 vector extensions and friends.  */
 -  if (precision > HOST_BITS_PER_DOUBLE_INT)
 -    precision = HOST_BITS_PER_DOUBLE_INT;
 -
    TYPE_UNSIGNED (type) = 1;
  
 -  set_min_and_max_values_for_integral_type (type, precision,
 -                                          /*is_unsigned=*/true);
 +  set_min_and_max_values_for_integral_type (type, precision, UNSIGNED);
  
    /* Lay out the type: set its alignment, size, etc.  */
    layout_type (type);
diff --combined gcc/targhooks.c
index eb2e02f7c6223e02659c6e74406be57b925469cc,7585c14b56ff28b03eca1feb4aeee46c6cec2bf0..fe3c7d0cac6554ff2a3de82e78a2bdf93242297b
@@@ -68,7 -68,8 +68,8 @@@ along with GCC; see the file COPYING3
  #include "recog.h"
  #include "intl.h"
  #include "opts.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "tree-ssanames.h"
  #include "tree-ssa-alias.h"
  #include "insn-codes.h"
  
@@@ -288,7 -289,7 +289,7 @@@ default_cxx_get_cookie_size (tree type
  
    sizetype_size = size_in_bytes (sizetype);
    type_align = size_int (TYPE_ALIGN_UNIT (type));
 -  if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
 +  if (INT_CST_LT (type_align, sizetype_size))
      cookie_size = sizetype_size;
    else
      cookie_size = type_align;
@@@ -435,6 -436,19 +436,19 @@@ targhook_float_words_big_endian (void
    return !!FLOAT_WORDS_BIG_ENDIAN;
  }
  
+ /* True if the target supports floating-point exceptions and rounding
+    modes.  */
+ bool
+ default_float_exceptions_rounding_supported_p (void)
+ {
+ #ifdef HAVE_adddf3
+   return HAVE_adddf3;
+ #else
+   return false;
+ #endif
+ }
  /* True if the target supports decimal floating point.  */
  
  bool
@@@ -979,7 -993,7 +993,7 @@@ tree default_mangle_decl_assembler_nam
  HOST_WIDE_INT
  default_vector_alignment (const_tree type)
  {
 -  return tree_low_cst (TYPE_SIZE (type), 0);
 +  return tree_to_shwi (TYPE_SIZE (type));
  }
  
  bool
@@@ -1556,6 -1570,28 +1570,28 @@@ default_member_type_forces_blk (const_t
  {
    return false;
  }
+ rtx
+ default_load_bounds_for_arg (rtx addr ATTRIBUTE_UNUSED,
+                            rtx ptr ATTRIBUTE_UNUSED,
+                            rtx bnd ATTRIBUTE_UNUSED)
+ {
+   gcc_unreachable ();
+ }
+ void
+ default_store_bounds_for_arg (rtx val ATTRIBUTE_UNUSED,
+                             rtx addr ATTRIBUTE_UNUSED,
+                             rtx bounds ATTRIBUTE_UNUSED,
+                             rtx to ATTRIBUTE_UNUSED)
+ {
+   gcc_unreachable ();
+ }
+ tree
+ default_fn_abi_va_list_bounds_size (tree fndecl ATTRIBUTE_UNUSED)
+ {
+   return integer_zero_node;
+ }
  
  /* Default version of canonicalize_comparison.  */
  
@@@ -1564,4 -1600,136 +1600,136 @@@ default_canonicalize_comparison (int *
  {
  }
  
+ #ifndef PAD_VARARGS_DOWN
+ #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
+ #endif
+ /* Build an indirect-ref expression over the given TREE, which represents a
+    piece of a va_arg() expansion.  */
+ tree
+ build_va_arg_indirect_ref (tree addr)
+ {
+   addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr);
+   return addr;
+ }
+ /* The "standard" implementation of va_arg: read the value from the
+    current (padded) address and increment by the (padded) size.  */
+ tree
+ std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
+                         gimple_seq *post_p)
+ {
+   tree addr, t, type_size, rounded_size, valist_tmp;
+   unsigned HOST_WIDE_INT align, boundary;
+   bool indirect;
+ #ifdef ARGS_GROW_DOWNWARD
+   /* All of the alignment and movement below is for args-grow-up machines.
+      As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
+      implement their own specialized gimplify_va_arg_expr routines.  */
+   gcc_unreachable ();
+ #endif
+   indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+   if (indirect)
+     type = build_pointer_type (type);
+   align = PARM_BOUNDARY / BITS_PER_UNIT;
+   boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
+   /* When we align parameter on stack for caller, if the parameter
+      alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
+      aligned at MAX_SUPPORTED_STACK_ALIGNMENT.  We will match callee
+      here with caller.  */
+   if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
+     boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
+   boundary /= BITS_PER_UNIT;
+   /* Hoist the valist value into a temporary for the moment.  */
+   valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
+   /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
+      requires greater alignment, we must perform dynamic alignment.  */
+   if (boundary > align
+       && !integer_zerop (TYPE_SIZE (type)))
+     {
+       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+                 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
+       gimplify_and_add (t, pre_p);
+       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+                 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
+                              valist_tmp,
+                              build_int_cst (TREE_TYPE (valist), -boundary)));
+       gimplify_and_add (t, pre_p);
+     }
+   else
+     boundary = align;
+   /* If the actual alignment is less than the alignment of the type,
+      adjust the type accordingly so that we don't assume strict alignment
+      when dereferencing the pointer.  */
+   boundary *= BITS_PER_UNIT;
+   if (boundary < TYPE_ALIGN (type))
+     {
+       type = build_variant_type_copy (type);
+       TYPE_ALIGN (type) = boundary;
+     }
+   /* Compute the rounded size of the type.  */
+   type_size = size_in_bytes (type);
+   rounded_size = round_up (type_size, align);
+   /* Reduce rounded_size so it's sharable with the postqueue.  */
+   gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
+   /* Get AP.  */
+   addr = valist_tmp;
+   if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
+     {
+       /* Small args are padded downward.  */
+       t = fold_build2_loc (input_location, GT_EXPR, sizetype,
+                      rounded_size, size_int (align));
+       t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
+                      size_binop (MINUS_EXPR, rounded_size, type_size));
+       addr = fold_build_pointer_plus (addr, t);
+     }
+   /* Compute new value for AP.  */
+   t = fold_build_pointer_plus (valist_tmp, rounded_size);
+   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
+   gimplify_and_add (t, pre_p);
+   addr = fold_convert (build_pointer_type (type), addr);
+   if (indirect)
+     addr = build_va_arg_indirect_ref (addr);
+   return build_va_arg_indirect_ref (addr);
+ }
+ tree
+ default_chkp_bound_type (void)
+ {
+   tree res = make_node (POINTER_BOUNDS_TYPE);
+   TYPE_PRECISION (res) = TYPE_PRECISION (size_type_node) * 2;
+   layout_type (res);
+   return res;
+ }
+ enum machine_mode
+ default_chkp_bound_mode (void)
+ {
+   return VOIDmode;
+ }
+ tree
+ default_builtin_chkp_function (unsigned int fcode ATTRIBUTE_UNUSED)
+ {
+   return NULL_TREE;
+ }
  #include "gt-targhooks.h"
diff --combined gcc/trans-mem.c
index 3371c7ea26edb885eb0ecacb6d2110b9ac64cb46,d74455d2bbcfaf545e402b7fe4fa4d2302e2485c..9ba2a38814e158fde4644c6c964c35614e5956f4
  #include "hash-table.h"
  #include "tree.h"
  #include "gimple.h"
- #include "tree-ssa.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-ssanames.h"
+ #include "tree-into-ssa.h"
  #include "tree-pass.h"
  #include "tree-inline.h"
  #include "diagnostic-core.h"
@@@ -1073,8 -1077,8 +1077,8 @@@ tm_log_add (basic_block entry_block, tr
        if (entry_block
          && transaction_invariant_address_p (lp->addr, entry_block)
          && TYPE_SIZE_UNIT (type) != NULL
 -        && host_integerp (TYPE_SIZE_UNIT (type), 1)
 -        && (tree_low_cst (TYPE_SIZE_UNIT (type), 1)
 +        && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
 +        && ((HOST_WIDE_INT)(tree_to_uhwi (TYPE_SIZE_UNIT (type)))
              < PARAM_VALUE (PARAM_TM_MAX_AGGREGATE_SIZE))
          /* We must be able to copy this type normally.  I.e., no
             special constructors and the like.  */
@@@ -1157,9 -1161,9 +1161,9 @@@ tm_log_emit_stmt (tree addr, gimple stm
      code = BUILT_IN_TM_LOG_DOUBLE;
    else if (type == long_double_type_node)
      code = BUILT_IN_TM_LOG_LDOUBLE;
 -  else if (host_integerp (size, 1))
 +  else if (tree_fits_uhwi_p (size))
      {
 -      unsigned int n = tree_low_cst (size, 1);
 +      unsigned int n = tree_to_uhwi (size);
        switch (n)
        {
        case 1:
@@@ -2075,9 -2079,9 +2079,9 @@@ build_tm_load (location_t loc, tree lhs
    else if (type == long_double_type_node)
      code = BUILT_IN_TM_LOAD_LDOUBLE;
    else if (TYPE_SIZE_UNIT (type) != NULL
 -         && host_integerp (TYPE_SIZE_UNIT (type), 1))
 +         && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
      {
 -      switch (tree_low_cst (TYPE_SIZE_UNIT (type), 1))
 +      switch (tree_to_uhwi (TYPE_SIZE_UNIT (type)))
        {
        case 1:
          code = BUILT_IN_TM_LOAD_1;
@@@ -2147,9 -2151,9 +2151,9 @@@ build_tm_store (location_t loc, tree lh
    else if (type == long_double_type_node)
      code = BUILT_IN_TM_STORE_LDOUBLE;
    else if (TYPE_SIZE_UNIT (type) != NULL
 -         && host_integerp (TYPE_SIZE_UNIT (type), 1))
 +         && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
      {
 -      switch (tree_low_cst (TYPE_SIZE_UNIT (type), 1))
 +      switch (tree_to_uhwi (TYPE_SIZE_UNIT (type)))
        {
        case 1:
          code = BUILT_IN_TM_STORE_1;
@@@ -3088,7 -3092,7 +3092,7 @@@ expand_block_edges (struct tm_region *c
          // TM_ABORT directly get what they deserve.
          tree arg = gimple_call_arg (stmt, 0);
          if (TREE_CODE (arg) == INTEGER_CST
 -            && (TREE_INT_CST_LOW (arg) & AR_OUTERABORT) != 0
 +            && (tree_to_hwi (arg) & AR_OUTERABORT) != 0
              && !decl_is_tm_clone (current_function_decl))
            {
              // Find the GTMA_IS_OUTER transaction.
@@@ -4036,16 -4040,16 +4040,16 @@@ get_cg_data (struct cgraph_node **node
  {
    struct tm_ipa_cg_data *d;
  
-   if (traverse_aliases && (*node)->symbol.alias)
+   if (traverse_aliases && (*node)->alias)
      *node = cgraph_alias_target (*node);
  
-   d = (struct tm_ipa_cg_data *) (*node)->symbol.aux;
+   d = (struct tm_ipa_cg_data *) (*node)->aux;
  
    if (d == NULL)
      {
        d = (struct tm_ipa_cg_data *)
        obstack_alloc (&tm_obstack.obstack, sizeof (*d));
-       (*node)->symbol.aux = (void *) d;
+       (*node)->aux = (void *) d;
        memset (d, 0, sizeof (*d));
      }
  
@@@ -4188,7 -4192,7 +4192,7 @@@ static voi
  ipa_tm_scan_calls_clone (struct cgraph_node *node,
                         cgraph_node_queue *callees_p)
  {
-   struct function *fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
+   struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
    basic_block bb;
  
    FOR_EACH_BB_FN (bb, fn)
@@@ -4217,7 -4221,7 +4221,7 @@@ ipa_tm_note_irrevocable (struct cgraph_
        continue;
        /* Even if we think we can go irrevocable, believe the user
         above all.  */
-       if (is_tm_safe_or_pure (e->caller->symbol.decl))
+       if (is_tm_safe_or_pure (e->caller->decl))
        continue;
  
        caller = e->caller;
@@@ -4489,11 -4493,11 +4493,11 @@@ ipa_tm_scan_irr_function (struct cgraph
    bool ret = false;
  
    /* Builtin operators (operator new, and such).  */
-   if (DECL_STRUCT_FUNCTION (node->symbol.decl) == NULL
-       || DECL_STRUCT_FUNCTION (node->symbol.decl)->cfg == NULL)
+   if (DECL_STRUCT_FUNCTION (node->decl) == NULL
+       || DECL_STRUCT_FUNCTION (node->decl)->cfg == NULL)
      return false;
  
-   push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
    calculate_dominance_info (CDI_DOMINATORS);
  
    d = get_cg_data (&node, true);
@@@ -4579,7 -4583,7 +4583,7 @@@ ipa_tm_mayenterirr_function (struct cgr
    unsigned flags;
  
    d = get_cg_data (&node, true);
-   decl = node->symbol.decl;
+   decl = node->decl;
    flags = flags_from_decl_or_type (decl);
  
    /* Handle some TM builtins.  Ordinarily these aren't actually generated
    /* Recurse on the main body for aliases.  In general, this will
       result in one of the bits above being set so that we will not
       have to recurse next time.  */
-   if (node->symbol.alias)
+   if (node->alias)
      return ipa_tm_mayenterirr_function (cgraph_get_node (node->thunk.alias));
  
    /* What remains is unmarked local functions without items that force
@@@ -4639,11 -4643,11 +4643,11 @@@ ipa_tm_diagnose_tm_safe (struct cgraph_
    struct cgraph_edge *e;
  
    for (e = node->callees; e ; e = e->next_callee)
-     if (!is_tm_callable (e->callee->symbol.decl)
+     if (!is_tm_callable (e->callee->decl)
        && e->callee->local.tm_may_enter_irr)
        error_at (gimple_location (e->call_stmt),
                "unsafe function call %qD within "
-               "%<transaction_safe%> function", e->callee->symbol.decl);
+               "%<transaction_safe%> function", e->callee->decl);
  }
  
  /* Diagnose call from atomic transactions to unmarked functions
@@@ -4782,14 -4786,14 +4786,14 @@@ static inline voi
  ipa_tm_mark_force_output_node (struct cgraph_node *node)
  {
    cgraph_mark_force_output_node (node);
-   node->symbol.analyzed = true;
+   node->analyzed = true;
  }
  
  static inline void
  ipa_tm_mark_forced_by_abi_node (struct cgraph_node *node)
  {
-   node->symbol.forced_by_abi = true;
-   node->symbol.analyzed = true;
+   node->forced_by_abi = true;
+   node->analyzed = true;
  }
  
  /* Callback data for ipa_tm_create_version_alias.  */
@@@ -4810,10 -4814,10 +4814,10 @@@ ipa_tm_create_version_alias (struct cgr
    tree old_decl, new_decl, tm_name;
    struct cgraph_node *new_node;
  
-   if (!node->symbol.cpp_implicit_alias)
+   if (!node->cpp_implicit_alias)
      return false;
  
-   old_decl = node->symbol.decl;
+   old_decl = node->decl;
    tm_name = tm_mangle (DECL_ASSEMBLER_NAME (old_decl));
    new_decl = build_decl (DECL_SOURCE_LOCATION (old_decl),
                         TREE_CODE (old_decl), tm_name,
  
    new_node = cgraph_same_body_alias (NULL, new_decl, info->new_decl);
    new_node->tm_clone = true;
-   new_node->symbol.externally_visible = info->old_node->symbol.externally_visible;
+   new_node->externally_visible = info->old_node->externally_visible;
    /* ?? Do not traverse aliases here.  */
    get_cg_data (&node, false)->clone = new_node;
  
    record_tm_clone_pair (old_decl, new_decl);
  
-   if (info->old_node->symbol.force_output
-       || ipa_ref_list_first_referring (&info->old_node->symbol.ref_list))
+   if (info->old_node->force_output
+       || ipa_ref_list_first_referring (&info->old_node->ref_list))
      ipa_tm_mark_force_output_node (new_node);
-   if (info->old_node->symbol.forced_by_abi)
+   if (info->old_node->forced_by_abi)
      ipa_tm_mark_forced_by_abi_node (new_node);
    return false;
  }
@@@ -4862,7 -4866,7 +4866,7 @@@ ipa_tm_create_version (struct cgraph_no
    tree new_decl, old_decl, tm_name;
    struct cgraph_node *new_node;
  
-   old_decl = old_node->symbol.decl;
+   old_decl = old_node->decl;
    new_decl = copy_node (old_decl);
  
    /* DECL_ASSEMBLER_NAME needs to be set before we call
  
    new_node = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
    new_node->local.local = false;
-   new_node->symbol.externally_visible = old_node->symbol.externally_visible;
+   new_node->externally_visible = old_node->externally_visible;
    new_node->lowered = true;
    new_node->tm_clone = 1;
    get_cg_data (&old_node, true)->clone = new_node;
    record_tm_clone_pair (old_decl, new_decl);
  
    cgraph_call_function_insertion_hooks (new_node);
-   if (old_node->symbol.force_output
-       || ipa_ref_list_first_referring (&old_node->symbol.ref_list))
+   if (old_node->force_output
+       || ipa_ref_list_first_referring (&old_node->ref_list))
      ipa_tm_mark_force_output_node (new_node);
-   if (old_node->symbol.forced_by_abi)
+   if (old_node->forced_by_abi)
      ipa_tm_mark_forced_by_abi_node (new_node);
  
    /* Do the same thing, but for any aliases of the original node.  */
@@@ -4941,7 -4945,7 +4945,7 @@@ ipa_tm_insert_irr_call (struct cgraph_n
               cgraph_get_create_node
                  (builtin_decl_explicit (BUILT_IN_TM_IRREVOCABLE)),
                      g, 0,
-                     compute_call_stmt_bb_frequency (node->symbol.decl,
+                     compute_call_stmt_bb_frequency (node->decl,
                                                      gimple_bb (g)));
  }
  
@@@ -4991,7 -4995,7 +4995,7 @@@ ipa_tm_insert_gettmclone_call (struct c
    gsi_insert_before (gsi, g, GSI_SAME_STMT);
  
    cgraph_create_edge (node, cgraph_get_create_node (gettm_fn), g, 0,
-                     compute_call_stmt_bb_frequency (node->symbol.decl,
+                     compute_call_stmt_bb_frequency (node->decl,
                                                      gimple_bb (g)));
  
    /* Cast return value from tm_gettmclone* into appropriate function
@@@ -5118,7 -5122,7 +5122,7 @@@ ipa_tm_transform_calls_redirect (struc
          return;
        }
  
-       fndecl = new_node->symbol.decl;
+       fndecl = new_node->decl;
      }
  
    cgraph_redirect_edge_callee (e, new_node);
@@@ -5212,7 -5216,7 +5216,7 @@@ ipa_tm_transform_transaction (struct cg
  
    d = get_cg_data (&node, true);
  
-   push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
    calculate_dominance_info (CDI_DOMINATORS);
  
    for (region = d->all_tm_regions; region; region = region->next)
@@@ -5255,7 -5259,7 +5259,7 @@@ ipa_tm_transform_clone (struct cgraph_n
    if (!node->callees && !node->indirect_calls && !d->irrevocable_blocks_clone)
      return;
  
-   push_cfun (DECL_STRUCT_FUNCTION (d->clone->symbol.decl));
+   push_cfun (DECL_STRUCT_FUNCTION (d->clone->decl));
    calculate_dominance_info (CDI_DOMINATORS);
  
    need_ssa_rename =
@@@ -5291,7 -5295,7 +5295,7 @@@ ipa_tm_execute (void
  
    /* For all local functions marked tm_callable, queue them.  */
    FOR_EACH_DEFINED_FUNCTION (node)
-     if (is_tm_callable (node->symbol.decl)
+     if (is_tm_callable (node->decl)
        && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
        d = get_cg_data (&node, true);
        /* ... marked tm_pure, record that fact for the runtime by
           indicating that the pure function is its own tm_callable.
           No need to do this if the function's address can't be taken.  */
-       if (is_tm_pure (node->symbol.decl))
+       if (is_tm_pure (node->decl))
          {
            if (!node->local.local)
-             record_tm_clone_pair (node->symbol.decl, node->symbol.decl);
+             record_tm_clone_pair (node->decl, node->decl);
            continue;
          }
  
-       push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
        calculate_dominance_info (CDI_DOMINATORS);
  
        tm_region_init (NULL);
  
        /* Some callees cannot be arbitrarily cloned.  These will always be
         irrevocable.  Mark these now, so that we need not scan them.  */
-       if (is_tm_irrevocable (node->symbol.decl))
+       if (is_tm_irrevocable (node->decl))
        ipa_tm_note_irrevocable (node, &irr_worklist);
        else if (a <= AVAIL_NOT_AVAILABLE
-              && !is_tm_safe_or_pure (node->symbol.decl))
+              && !is_tm_safe_or_pure (node->decl))
        ipa_tm_note_irrevocable (node, &irr_worklist);
        else if (a >= AVAIL_OVERWRITABLE)
        {
-         if (!tree_versionable_function_p (node->symbol.decl))
+         if (!tree_versionable_function_p (node->decl))
            ipa_tm_note_irrevocable (node, &irr_worklist);
          else if (!d->is_irrevocable)
            {
              /* If this is an alias, make sure its base is queued as well.
                 we need not scan the callees now, as the base will do.  */
-             if (node->symbol.alias)
+             if (node->alias)
                {
                  node = cgraph_get_node (node->thunk.alias);
                  d = get_cg_data (&node, true);
        for (e = node->callers; e ; e = e->next_caller)
        {
          caller = e->caller;
-         if (!is_tm_safe_or_pure (caller->symbol.decl)
+         if (!is_tm_safe_or_pure (caller->decl)
              && !caller->local.tm_may_enter_irr)
            {
              d = get_cg_data (&caller, true);
        }
  
        /* Propagate back to referring aliases as well.  */
-       for (j = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, j, ref); j++)
+       for (j = 0; ipa_ref_list_referring_iterate (&node->ref_list, j, ref); j++)
        {
          caller = cgraph (ref->referring);
          if (ref->use == IPA_REF_ALIAS
        && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
        d = get_cg_data (&node, true);
-       if (is_tm_safe (node->symbol.decl))
+       if (is_tm_safe (node->decl))
          ipa_tm_diagnose_tm_safe (node);
        else if (d->all_tm_regions)
          ipa_tm_diagnose_transaction (node, d->all_tm_regions);
        bool doit = false;
  
        node = tm_callees[i];
-       if (node->symbol.cpp_implicit_alias)
+       if (node->cpp_implicit_alias)
        continue;
  
        a = cgraph_function_body_availability (node);
        d = get_cg_data (&node, true);
  
        if (a <= AVAIL_NOT_AVAILABLE)
-       doit = is_tm_callable (node->symbol.decl);
-       else if (a <= AVAIL_AVAILABLE && is_tm_callable (node->symbol.decl))
+       doit = is_tm_callable (node->decl);
+       else if (a <= AVAIL_AVAILABLE && is_tm_callable (node->decl))
        doit = true;
        else if (!d->is_irrevocable
               && d->tm_callers_normal + d->tm_callers_clone > 0)
    for (i = 0; i < tm_callees.length (); ++i)
      {
        node = tm_callees[i];
-       if (node->symbol.analyzed)
+       if (node->analyzed)
        {
          d = get_cg_data (&node, true);
          if (d->clone)
    free_original_copy_tables ();
  
    FOR_EACH_FUNCTION (node)
-     node->symbol.aux = NULL;
+     node->aux = NULL;
  
  #ifdef ENABLE_CHECKING
    verify_cgraph ();
diff --combined gcc/tree-call-cdce.c
index fa41e297e1b0a5895282e70ea21bb18ed46d6c41,eec1b0fb739aa3f1842f14c1e1cdeb58c65a85d1..58065ad8377e06f51f2f8d054f18cc11d634e4b8
@@@ -25,8 -25,11 +25,11 @@@ along with GCC; see the file COPYING3
  #include "basic-block.h"
  #include "tree.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
  #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-ssanames.h"
+ #include "tree-into-ssa.h"
  #include "tree-pass.h"
  #include "flags.h"
  \f
@@@ -195,7 -198,7 +198,7 @@@ check_pow (gimple pow_call
          return false;
        if (REAL_VALUES_LESS (bcv, dconst1))
          return false;
 -      real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, 0, 1);
 +      real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
        if (REAL_VALUES_LESS (mv, bcv))
          return false;
        return true;
@@@ -412,7 -415,7 +415,7 @@@ gen_conditions_for_pow_cst_base (tree b
    REAL_VALUE_TYPE bcv = TREE_REAL_CST (base);
    gcc_assert (!REAL_VALUES_EQUAL (bcv, dconst1)
                && !REAL_VALUES_LESS (bcv, dconst1));
 -  real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, 0, 1);
 +  real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
    gcc_assert (!REAL_VALUES_LESS (mv, bcv));
  
    exp_domain = get_domain (0, false, false,
@@@ -710,7 -713,6 +713,6 @@@ shrink_wrap_one_built_in_call (gimple b
    basic_block bi_call_bb, join_tgt_bb, guard_bb, guard_bb0;
    edge join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru;
    edge bi_call_in_edge0, guard_bb_in_edge;
-   vec<gimple> conds;
    unsigned tn_cond_stmts, nconds;
    unsigned ci;
    gimple cond_expr = NULL;
    tree bi_call_label_decl;
    gimple bi_call_label;
  
-   conds.create (12);
+   stack_vec<gimple, 12> conds;
    gen_shrink_wrap_conditions (bi_call, conds, &nconds);
  
    /* This can happen if the condition generator decides
       return false and do not do any transformation for
       the call.  */
    if (nconds == 0)
-     {
-       conds.release ();
-       return false;
-     }
+     return false;
  
    bi_call_bb = gimple_bb (bi_call);
  
         it could e.g. have EH edges.  */
        join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
        if (join_tgt_in_edge_from_call == NULL)
-       {
-         conds.release ();
-         return false;
-       }
+         return false;
      }
    else
      join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
        guard_bb_in_edge->count = guard_bb->count - bi_call_in_edge->count;
      }
  
-   conds.release ();
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
        location_t loc;
diff --combined gcc/tree-cfg.c
index 94be3610c9102e34613e917e1ca3ae55837a5533,d646693903259340de65f4f5beb20a4f59df8e02..6c551f4fe96237e4008dc19bfba15dc13e254fff
@@@ -30,6 -30,17 +30,17 @@@ along with GCC; see the file COPYING3
  #include "function.h"
  #include "ggc.h"
  #include "gimple-pretty-print.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-into-ssa.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "tree-dump.h"
  #include "tree-pass.h"
@@@ -44,8 -55,6 +55,8 @@@
  #include "tree-ssa-live.h"
  #include "omp-low.h"
  #include "tree-cfgcleanup.h"
 +#include "wide-int.h"
 +#include "wide-int-print.h"
  
  /* This file contains functions for building the Control Flow Graph (CFG)
     for a function tree.  */
@@@ -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)
  {
      }
    cleanup_tree_cfg ();
    loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+   replace_loop_annotate ();
    return 0;
  }
  
@@@ -305,6 -381,50 +383,50 @@@ computed_goto_p (gimple t
          && TREE_CODE (gimple_goto_dest (t)) != LABEL_DECL);
  }
  
+ /* Returns true for edge E where e->src ends with a GIMPLE_COND and
+    the other edge points to a bb with just __builtin_unreachable ().
+    I.e. return true for C->M edge in:
+    <bb C>:
+    ...
+    if (something)
+      goto <bb N>;
+    else
+      goto <bb M>;
+    <bb N>:
+    __builtin_unreachable ();
+    <bb M>:  */
+ bool
+ assert_unreachable_fallthru_edge_p (edge e)
+ {
+   basic_block pred_bb = e->src;
+   gimple last = last_stmt (pred_bb);
+   if (last && gimple_code (last) == GIMPLE_COND)
+     {
+       basic_block other_bb = EDGE_SUCC (pred_bb, 0)->dest;
+       if (other_bb == e->dest)
+       other_bb = EDGE_SUCC (pred_bb, 1)->dest;
+       if (EDGE_COUNT (other_bb->succs) == 0)
+       {
+         gimple_stmt_iterator gsi = gsi_after_labels (other_bb);
+         gimple stmt;
+         if (gsi_end_p (gsi))
+           return false;
+         stmt = gsi_stmt (gsi);
+         if (is_gimple_debug (stmt))
+           {
+             gsi_next_nondebug (&gsi);
+             if (gsi_end_p (gsi))
+               return false;
+             stmt = gsi_stmt (gsi);
+           }
+         return gimple_call_builtin_p (stmt, BUILT_IN_UNREACHABLE);
+       }
+     }
+   return false;
+ }
  
  /* Search the CFG for any computed gotos.  If found, factor them to a
     common computed goto site.  Also record the location of that site so
@@@ -1306,12 -1426,12 +1428,12 @@@ group_case_labels_stmt (gimple stmt
        {
          tree merge_case = gimple_switch_label (stmt, i);
          basic_block merge_bb = label_to_block (CASE_LABEL (merge_case));
 -        double_int bhp1 = tree_to_double_int (base_high) + double_int_one;
 +        wide_int bhp1 = wi::add (base_high, 1);
  
          /* Merge the cases if they jump to the same place,
             and their ranges are consecutive.  */
          if (merge_bb == base_bb
 -            && tree_to_double_int (CASE_LOW (merge_case)) == bhp1)
 +            && wi::eq_p (CASE_LOW (merge_case), bhp1))
            {
              base_high = CASE_HIGH (merge_case) ?
                  CASE_HIGH (merge_case) : CASE_LOW (merge_case);
@@@ -2578,25 -2698,24 +2700,25 @@@ verify_expr (tree *tp, int *walk_subtre
  
        if (TREE_CODE (t) == BIT_FIELD_REF)
        {
 -        if (!host_integerp (TREE_OPERAND (t, 1), 1)
 -            || !host_integerp (TREE_OPERAND (t, 2), 1))
 +        if (!tree_fits_uhwi_p (TREE_OPERAND (t, 1))
 +            || !tree_fits_uhwi_p (TREE_OPERAND (t, 2)))
            {
              error ("invalid position or size operand to BIT_FIELD_REF");
              return t;
            }
          if (INTEGRAL_TYPE_P (TREE_TYPE (t))
              && (TYPE_PRECISION (TREE_TYPE (t))
 -                != TREE_INT_CST_LOW (TREE_OPERAND (t, 1))))
 +                != tree_to_uhwi (TREE_OPERAND (t, 1))))
            {
              error ("integral result type precision does not match "
                     "field size of BIT_FIELD_REF");
              return t;
            }
          else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
 +                 && !AGGREGATE_TYPE_P (TREE_TYPE (t))
                   && TYPE_MODE (TREE_TYPE (t)) != BLKmode
                   && (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (t)))
 -                     != TREE_INT_CST_LOW (TREE_OPERAND (t, 1))))
 +                     != tree_to_uhwi (TREE_OPERAND (t, 1))))
            {
              error ("mode precision of non-integral result does not "
                     "match field size of BIT_FIELD_REF");
@@@ -3405,7 -3524,7 +3527,7 @@@ verify_gimple_assign_binary (gimple stm
           only allow shifting by a constant multiple of the element size.  */
        if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
            && (TREE_CODE (rhs2) != INTEGER_CST
 -              || !div_if_zero_remainder (EXACT_DIV_EXPR, rhs2,
 +              || !div_if_zero_remainder (rhs2,
                                           TYPE_SIZE (TREE_TYPE (rhs1_type)))))
          {
            error ("non-element sized vector shift of floating point vector");
@@@ -6151,7 -6270,7 +6273,7 @@@ move_stmt_eh_region_tree_nr (tree old_t
  {
    int old_nr, new_nr;
  
 -  old_nr = tree_low_cst (old_t_nr, 0);
 +  old_nr = tree_to_shwi (old_t_nr);
    new_nr = move_stmt_eh_region_nr (old_nr, p);
  
    return build_int_cst (integer_type_node, new_nr);
@@@ -7075,13 -7194,13 +7197,13 @@@ print_loop (FILE *file, struct loop *lo
    if (loop->any_upper_bound)
      {
        fprintf (file, ", upper_bound = ");
 -      dump_double_int (file, loop->nb_iterations_upper_bound, true);
 +      print_decu (loop->nb_iterations_upper_bound, file);
      }
  
    if (loop->any_estimate)
      {
        fprintf (file, ", estimate = ");
 -      dump_double_int (file, loop->nb_iterations_estimate, true);
 +      print_decu (loop->nb_iterations_estimate, file);
      }
    fprintf (file, ")\n");
  
diff --combined gcc/tree-chrec.c
index 1d02da669fda996ca1a8ab711b155819ee9d2aae,afc1a6a5f645d631f6ab0f268c3df82b3e85a8e2..91a14e41f53a8d2ca8cd1a7891cf78c3fffaf963
@@@ -29,7 -29,9 +29,9 @@@ along with GCC; see the file COPYING3
  #include "tree.h"
  #include "tree-pretty-print.h"
  #include "cfgloop.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "tree-ssa-loop-ivopts.h"
+ #include "tree-ssa-loop-niter.h"
  #include "tree-chrec.h"
  #include "dumpfile.h"
  #include "params.h"
@@@ -477,6 -479,7 +479,6 @@@ chrec_fold_multiply (tree type
  static tree
  tree_fold_binomial (tree type, tree n, unsigned int k)
  {
 -  double_int num, denom, idx, di_res;
    bool overflow;
    unsigned int i;
    tree res;
      return fold_convert (type, n);
  
    /* Numerator = n.  */
 -  num = TREE_INT_CST (n);
 +  wide_int num = n;
  
    /* Check that k <= n.  */
 -  if (num.ult (double_int::from_uhwi (k)))
 +  if (wi::ltu_p (num, k))
      return NULL_TREE;
  
    /* Denominator = 2.  */
 -  denom = double_int::from_uhwi (2);
 +  wide_int denom = wi::two (TYPE_PRECISION (TREE_TYPE (n)));
  
    /* Index = Numerator-1.  */
 -  idx = num - double_int_one;
 +  wide_int idx = num - 1;
  
    /* Numerator = Numerator*Index = n*(n-1).  */
 -  num = num.mul_with_sign (idx, false, &overflow);
 +  num = wi::smul (num, idx, &overflow);
    if (overflow)
      return NULL_TREE;
  
        --idx;
  
        /* Numerator *= Index.  */
 -      num = num.mul_with_sign (idx, false, &overflow);
 +      num = wi::smul (num, idx, &overflow);
        if (overflow)
        return NULL_TREE;
  
        /* Denominator *= i.  */
 -      denom *= double_int::from_uhwi (i);
 +      denom *= i;
      }
  
    /* Result = Numerator / Denominator.  */
 -  di_res = num.div (denom, true, EXACT_DIV_EXPR);
 -  res = build_int_cst_wide (type, di_res.low, di_res.high);
 +  wide_int di_res = wi::udiv_trunc (num, denom);
 +  res = wide_int_to_tree (type, di_res);
    return int_fits_type_p (res, type) ? res : NULL_TREE;
  }
  
diff --combined gcc/tree-core.h
index 4aff4c9d1d5b5573071f02b79ac0ae331547f50c,638b3ab3f68c88164981edf9e709fa8013a39a15..a52893c7fb9a9f7a0c8fcafb5d2026700bd31e36
@@@ -448,6 -448,8 +448,8 @@@ enum tree_index 
    TI_FILEPTR_TYPE,
    TI_POINTER_SIZED_TYPE,
  
+   TI_POINTER_BOUNDS_TYPE,
    TI_DFLOAT32_TYPE,
    TI_DFLOAT64_TYPE,
    TI_DFLOAT128_TYPE,
@@@ -647,6 -649,10 +649,10 @@@ enum tree_node_kind 
    all_kinds
  };
  
+ enum annot_expr_kind {
+   annot_expr_ivdep_kind
+ };
  
  /*---------------------------------------------------------------------------
                                  Type definitions
@@@ -741,25 -747,11 +747,25 @@@ struct GTY(()) tree_base 
         of the field must be large enough to hold addr_space_t values.  */
        unsigned address_space : 8;
      } bits;
 +
      /* The following fields are present in tree_base to save space.  The
         nodes using them do not require any of the flags above and so can
         make better use of the 4-byte sized word.  */
 +
 +    /* The number of HOST_WIDE_INTs in an INTEGER_CST.  */
 +    struct {
 +      /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
 +       its native precision.  */
 +      unsigned short unextended;
 +
 +      /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to
 +       wider precisions based on its TYPE_SIGN.  */
 +      unsigned short extended;
 +    } int_length;
 +
      /* VEC length.  This field is only used with TREE_VEC.  */
      int length;
 +
      /* SSA version number.  This field is only used with SSA_NAME.  */
      unsigned int version;
    } GTY((skip(""))) u;
@@@ -1036,7 -1028,7 +1042,7 @@@ struct GTY(()) tree_common 
  
  struct GTY(()) tree_int_cst {
    struct tree_typed typed;
 -  double_int int_cst;
 +  HOST_WIDE_INT val[1];
  };
  
  
diff --combined gcc/tree-data-ref.c
index 6fa9f3b5abcf796665c05cf507fd8392ebdf033c,ffa4cbf14d7bca7cf92fa5f5942bc0329e29b91b..67528a8d7c568226c16532232c04da04e0aa0762
@@@ -78,6 -78,9 +78,9 @@@ along with GCC; see the file COPYING3
  #include "coretypes.h"
  #include "tree.h"
  #include "gimple-pretty-print.h"
+ #include "gimple.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
  #include "tree-ssa.h"
  #include "cfgloop.h"
  #include "tree-data-ref.h"
@@@ -773,8 -776,8 +776,8 @@@ dr_analyze_innermost (struct data_refer
      {
        if (!integer_zerop (TREE_OPERAND (base, 1)))
        {
 -        double_int moff = mem_ref_offset (base);
 -        tree mofft = double_int_to_tree (sizetype, moff);
 +        offset_int moff = mem_ref_offset (base);
 +        tree mofft = wide_int_to_tree (sizetype, moff);
          if (!poffset)
            poffset = mofft;
          else
@@@ -1370,10 -1373,10 +1373,10 @@@ dr_may_alias_p (const struct data_refer
    if (!loop_nest)
      {
        aff_tree off1, off2;
 -      double_int size1, size2;
 +      widest_int size1, size2;
        get_inner_reference_aff (DR_REF (a), &off1, &size1);
        get_inner_reference_aff (DR_REF (b), &off2, &size2);
 -      aff_combination_scale (&off1, double_int_minus_one);
 +      aff_combination_scale (&off1, -1);
        aff_combination_add (&off2, &off1);
        if (aff_comb_cannot_overlap_p (&off2, size1, size2))
        return false;
@@@ -1748,15 -1751,15 +1751,15 @@@ analyze_ziv_subscript (tree chrec_a
  static tree
  max_stmt_executions_tree (struct loop *loop)
  {
 -  double_int nit;
 +  widest_int nit;
  
    if (!max_stmt_executions (loop, &nit))
      return chrec_dont_know;
  
 -  if (!double_int_fits_to_tree_p (unsigned_type_node, nit))
 +  if (!wi::fits_to_tree_p (nit, unsigned_type_node))
      return chrec_dont_know;
  
 -  return double_int_to_tree (unsigned_type_node, nit);
 +  return wide_int_to_tree (unsigned_type_node, nit);
  }
  
  /* Determine whether the CHREC is always positive/negative.  If the expression
@@@ -2834,16 -2837,16 +2837,16 @@@ gcd_of_steps_may_divide_p (const_tree c
    HOST_WIDE_INT cd = 0, val;
    tree step;
  
 -  if (!host_integerp (cst, 0))
 +  if (!tree_fits_shwi_p (cst))
      return true;
 -  val = tree_low_cst (cst, 0);
 +  val = tree_to_shwi (cst);
  
    while (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
      {
        step = CHREC_RIGHT (chrec);
 -      if (!host_integerp (step, 0))
 +      if (!tree_fits_shwi_p (step))
        return true;
 -      cd = gcd (cd, tree_low_cst (step, 0));
 +      cd = gcd (cd, tree_to_shwi (step));
        chrec = CHREC_LEFT (chrec);
      }
  
@@@ -4322,7 -4325,7 +4325,7 @@@ typedef struct data_ref_loc_
     true if STMT clobbers memory, false otherwise.  */
  
  static bool
- get_references_in_stmt (gimple stmt, vec<data_ref_loc, va_stack> *references)
+ get_references_in_stmt (gimple stmt, vec<data_ref_loc, va_heap> *references)
  {
    bool clobbers_memory = false;
    data_ref_loc ref;
@@@ -4414,17 -4417,13 +4417,13 @@@ find_data_references_in_stmt (struct lo
                              vec<data_reference_p> *datarefs)
  {
    unsigned i;
-   vec<data_ref_loc, va_stack> references;
+   stack_vec<data_ref_loc, 2> references;
    data_ref_loc *ref;
    bool ret = true;
    data_reference_p dr;
  
-   vec_stack_alloc (data_ref_loc, references, 2);
    if (get_references_in_stmt (stmt, &references))
-     {
-       references.release ();
-       return false;
-     }
+     return false;
  
    FOR_EACH_VEC_ELT (references, i, ref)
      {
@@@ -4448,17 -4447,13 +4447,13 @@@ graphite_find_data_references_in_stmt (
                                       vec<data_reference_p> *datarefs)
  {
    unsigned i;
-   vec<data_ref_loc, va_stack> references;
+   stack_vec<data_ref_loc, 2> references;
    data_ref_loc *ref;
    bool ret = true;
    data_reference_p dr;
  
-   vec_stack_alloc (data_ref_loc, references, 2);
    if (get_references_in_stmt (stmt, &references))
-     {
-       references.release ();
-       return false;
-     }
+     return false;
  
    FOR_EACH_VEC_ELT (references, i, ref)
      {
diff --combined gcc/tree-dfa.c
index 688bf7e2041a1082e26b5496be7ac407aa9e9e1d,a44cfe884dd941404a9bc0f27fb55326389cd31d..13b27599aea995875e14bd7b86d06ab9c67b0566
@@@ -33,12 -33,15 +33,15 @@@ along with GCC; see the file COPYING3
  #include "function.h"
  #include "tree-pretty-print.h"
  #include "gimple.h"
- #include "tree-ssa.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "tree-inline.h"
  #include "tree-pass.h"
  #include "convert.h"
  #include "params.h"
- #include "cgraph.h"
  
  /* Build and maintain data flow information for trees.  */
  
@@@ -383,7 -386,7 +386,7 @@@ get_ref_base_and_extent (tree exp, HOST
    HOST_WIDE_INT bitsize = -1;
    HOST_WIDE_INT maxsize = -1;
    tree size_tree = NULL_TREE;
 -  double_int bit_offset = double_int_zero;
 +  offset_int bit_offset = 0;
    HOST_WIDE_INT hbit_offset;
    bool seen_variable_array_ref = false;
    tree base_type;
      }
    if (size_tree != NULL_TREE)
      {
 -      if (! host_integerp (size_tree, 1))
 +      if (! tree_fits_uhwi_p (size_tree))
        bitsize = -1;
        else
 -      bitsize = TREE_INT_CST_LOW (size_tree);
 +      bitsize = tree_to_uhwi (size_tree);
      }
  
    /* Initially, maxsize is the same as the accessed element size.
        switch (TREE_CODE (exp))
        {
        case BIT_FIELD_REF:
 -        bit_offset += tree_to_double_int (TREE_OPERAND (exp, 2));
 +        bit_offset += wi::to_offset (TREE_OPERAND (exp, 2));
          break;
  
        case COMPONENT_REF:
  
            if (this_offset && TREE_CODE (this_offset) == INTEGER_CST)
              {
 -              double_int doffset = tree_to_double_int (this_offset);
 -              doffset = doffset.lshift (BITS_PER_UNIT == 8
 -                                        ? 3 : exact_log2 (BITS_PER_UNIT));
 -              doffset += tree_to_double_int (DECL_FIELD_BIT_OFFSET (field));
 -              bit_offset = bit_offset + doffset;
 +              offset_int woffset = wi::to_offset (this_offset);
 +              woffset = wi::lshift (woffset,
 +                                    (BITS_PER_UNIT == 8
 +                                     ? 3 : exact_log2 (BITS_PER_UNIT)));
 +              woffset += wi::to_offset (DECL_FIELD_BIT_OFFSET (field));
 +              bit_offset += woffset;
  
                /* If we had seen a variable array ref already and we just
                   referenced the last field of a struct or a union member
                      {
                        tree fsize = DECL_SIZE_UNIT (field);
                        tree ssize = TYPE_SIZE_UNIT (stype);
 -                      if (host_integerp (fsize, 0)
 -                          && host_integerp (ssize, 0)
 -                          && doffset.fits_shwi ())
 -                        maxsize += ((TREE_INT_CST_LOW (ssize)
 -                                     - TREE_INT_CST_LOW (fsize))
 +                      if (tree_fits_shwi_p (fsize)
 +                          && tree_fits_shwi_p (ssize)
 +                          && wi::fits_shwi_p (woffset))
 +                        maxsize += ((tree_to_shwi (ssize)
 +                                     - tree_to_shwi (fsize))
                                      * BITS_PER_UNIT
 -                                      - doffset.to_shwi ());
 +                                      - woffset.to_shwi ());
                        else
                          maxsize = -1;
                      }
                   because that would get us out of the structure otherwise.  */
                if (maxsize != -1
                    && csize
 -                  && host_integerp (csize, 1)
 -                  && bit_offset.fits_shwi ())
 -                maxsize = TREE_INT_CST_LOW (csize)
 +                  && tree_fits_uhwi_p (csize)
 +                  && wi::fits_shwi_p (bit_offset))
 +                maxsize = tree_to_shwi (csize)
                            - bit_offset.to_shwi ();
                else
                  maxsize = -1;
                && (unit_size = array_ref_element_size (exp),
                    TREE_CODE (unit_size) == INTEGER_CST))
              {
 -              double_int doffset
 -                = (TREE_INT_CST (index) - TREE_INT_CST (low_bound))
 -                  .sext (TYPE_PRECISION (TREE_TYPE (index)));
 -              doffset *= tree_to_double_int (unit_size);
 -              doffset = doffset.lshift (BITS_PER_UNIT == 8
 -                                        ? 3 : exact_log2 (BITS_PER_UNIT));
 -              bit_offset = bit_offset + doffset;
 +              offset_int woffset
 +                = wi::sext (wi::to_offset (index) - wi::to_offset (low_bound),
 +                            TYPE_PRECISION (TREE_TYPE (index)));
 +              woffset *= wi::to_offset (unit_size);
 +              woffset = wi::lshift (woffset,
 +                                    (BITS_PER_UNIT == 8
 +                                     ? 3 : exact_log2 (BITS_PER_UNIT)));
 +              bit_offset += woffset;
  
                /* An array ref with a constant index up in the structure
                   hierarchy will constrain the size of any variable array ref
                   because that would get us outside of the array otherwise.  */
                if (maxsize != -1
                    && asize
 -                  && host_integerp (asize, 1)
 -                  && bit_offset.fits_shwi ())
 -                maxsize = TREE_INT_CST_LOW (asize)
 -                          - bit_offset.to_shwi ();
 +                  && tree_fits_uhwi_p (asize)
 +                  && wi::fits_shwi_p (bit_offset))
 +                maxsize = tree_to_uhwi (asize) - bit_offset.to_shwi ();
                else
                  maxsize = -1;
  
          break;
  
        case IMAGPART_EXPR:
 -        bit_offset += double_int::from_uhwi (bitsize);
 +        bit_offset += bitsize;
          break;
  
        case VIEW_CONVERT_EXPR:
                exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
              else
                {
 -                double_int off = mem_ref_offset (exp);
 -                off = off.lshift (BITS_PER_UNIT == 8
 -                                  ? 3 : exact_log2 (BITS_PER_UNIT));
 -                off = off + bit_offset;
 -                if (off.fits_shwi ())
 +                offset_int off = mem_ref_offset (exp);
 +                off = wi::lshift (off, (BITS_PER_UNIT == 8
 +                                        ? 3 : exact_log2 (BITS_PER_UNIT)));
 +                off += bit_offset;
 +                if (wi::fits_shwi_p (off))
                    {
                      bit_offset = off;
                      exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
              if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
                {
                  exp = TREE_OPERAND (TMR_BASE (exp), 0);
 -                bit_offset = double_int_zero;
 +                bit_offset = 0;
                  maxsize = -1;
                  goto done;
                }
                exp = TREE_OPERAND (TMR_BASE (exp), 0);
              else
                {
 -                double_int off = mem_ref_offset (exp);
 -                off = off.lshift (BITS_PER_UNIT == 8
 -                                  ? 3 : exact_log2 (BITS_PER_UNIT));
 +                offset_int off = mem_ref_offset (exp);
 +                off = wi::lshift (off, (BITS_PER_UNIT == 8
 +                                        ? 3 : exact_log2 (BITS_PER_UNIT)));
                  off += bit_offset;
 -                if (off.fits_shwi ())
 +                if (wi::fits_shwi_p (off))
                    {
                      bit_offset = off;
                      exp = TREE_OPERAND (TMR_BASE (exp), 0);
      }
   done:
  
 -  if (!bit_offset.fits_shwi ())
 +  if (!wi::fits_shwi_p (bit_offset))
      {
        *poffset = 0;
        *psize = bitsize;
  
    if (seen_variable_array_ref
        && maxsize != -1
 -      && (!host_integerp (TYPE_SIZE (base_type), 1)
 +      && (!tree_fits_uhwi_p (TYPE_SIZE (base_type))
          || (hbit_offset + maxsize
 -            == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type)))))
 +            == (signed) tree_to_uhwi (TYPE_SIZE (base_type)))))
      maxsize = -1;
  
    /* In case of a decl or constant base object we can do better.  */
        /* If maxsize is unknown adjust it according to the size of the
           base decl.  */
        if (maxsize == -1
 -        && host_integerp (DECL_SIZE (exp), 1))
 -      maxsize = TREE_INT_CST_LOW (DECL_SIZE (exp)) - hbit_offset;
 +        && tree_fits_uhwi_p (DECL_SIZE (exp)))
 +      maxsize = tree_to_uhwi (DECL_SIZE (exp)) - hbit_offset;
      }
    else if (CONSTANT_CLASS_P (exp))
      {
        /* If maxsize is unknown adjust it according to the size of the
           base type constant.  */
        if (maxsize == -1
 -        && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1))
 -      maxsize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))) - hbit_offset;
 +        && tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp))))
 +      maxsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp))) - hbit_offset;
      }
  
    /* ???  Due to negative offsets in ARRAY_REF we can end up with
@@@ -741,8 -743,7 +744,7 @@@ dump_enumerated_decls (FILE *file, int 
  {
    basic_block bb;
    struct walk_stmt_info wi;
-   vec<numbered_tree> decl_list;
-   decl_list.create (40);
+   stack_vec<numbered_tree, 40> decl_list;
  
    memset (&wi, '\0', sizeof (wi));
    wi.info = (void *) &decl_list;
          last = ntp->t;
        }
      }
-   decl_list.release ();
  }
diff --combined gcc/tree-inline.c
index 4543b270e5d5292bd6e7b58c5e9ff9de65584c3f,77013b390cb927902a407f63c775e688c0136c8e..2796ff22362a542c860c5ec5f453601f2838fc33
@@@ -33,12 -33,17 +33,17 @@@ along with GCC; see the file COPYING3
  #include "langhooks.h"
  #include "basic-block.h"
  #include "tree-iterator.h"
- #include "cgraph.h"
  #include "intl.h"
- #include "tree-mudflap.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-into-ssa.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "function.h"
- #include "tree-ssa.h"
  #include "tree-pretty-print.h"
  #include "except.h"
  #include "debug.h"
@@@ -53,7 -58,6 +58,6 @@@
  
  /* I'm not real happy about this, but we need to handle gimple and
     non-gimple trees.  */
- #include "gimple.h"
  
  /* Inlining, Cloning, Versioning, Parallelization
  
@@@ -839,7 -843,8 +843,7 @@@ remap_gimple_op_r (tree *tp, int *walk_
        *walk_subtrees = 0;
  
        else if (TREE_CODE (*tp) == INTEGER_CST)
 -      *tp = build_int_cst_wide (new_type, TREE_INT_CST_LOW (*tp),
 -                                TREE_INT_CST_HIGH (*tp));
 +      *tp = wide_int_to_tree (new_type, *tp);
        else
        {
          *tp = copy_node (*tp);
@@@ -1017,7 -1022,8 +1021,7 @@@ copy_tree_body_r (tree *tp, int *walk_s
        *walk_subtrees = 0;
  
        else if (TREE_CODE (*tp) == INTEGER_CST)
 -      *tp = build_int_cst_wide (new_type, TREE_INT_CST_LOW (*tp),
 -                                TREE_INT_CST_HIGH (*tp));
 +      *tp = wide_int_to_tree (new_type, *tp);
        else
        {
          *tp = copy_node (*tp);
@@@ -1211,7 -1217,7 +1215,7 @@@ remap_eh_region_tree_nr (tree old_t_nr
  {
    int old_nr, new_nr;
  
 -  old_nr = tree_low_cst (old_t_nr, 0);
 +  old_nr = tree_to_shwi (old_t_nr);
    new_nr = remap_eh_region_nr (old_nr, id);
  
    return build_int_cst (integer_type_node, new_nr);
@@@ -1740,7 -1746,7 +1744,7 @@@ copy_bb (copy_body_data *id, basic_bloc
                      /* We could also just rescale the frequency, but
                         doing so would introduce roundoff errors and make
                         verifier unhappy.  */
-                     new_freq  = compute_call_stmt_bb_frequency (id->dst_node->symbol.decl,
+                     new_freq  = compute_call_stmt_bb_frequency (id->dst_node->decl,
                                                                  copy_basic_block);
  
                      /* Speculative calls consist of two edges - direct and indirect.
                                                               (old_edge->frequency + indirect->frequency)),
                                                         CGRAPH_FREQ_MAX);
                            }
-                         ipa_clone_ref (ref, (symtab_node)id->dst_node, stmt);
+                         ipa_clone_ref (ref, id->dst_node, stmt);
                        }
                      else
                        {
              if ((!edge
                   || (edge->indirect_inlining_edge
                       && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
-                 && id->dst_node->symbol.definition
+                 && id->dst_node->definition
                  && (fn = gimple_call_fndecl (stmt)) != NULL)
                {
                  struct cgraph_node *dest = cgraph_get_node (fn);
                     producing dead clone (for further cloning).  In all
                     other cases we hit a bug (incorrect node sharing is the
                     most common reason for missing edges).  */
-                 gcc_assert (!dest->symbol.definition
-                             || dest->symbol.address_taken
-                             || !id->src_node->symbol.definition
-                             || !id->dst_node->symbol.definition);
+                 gcc_assert (!dest->definition
+                             || dest->address_taken
+                             || !id->src_node->definition
+                             || !id->dst_node->definition);
                  if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
                    cgraph_create_edge_including_clones
                      (id->dst_node, dest, orig_stmt, stmt, bb->count,
-                      compute_call_stmt_bb_frequency (id->dst_node->symbol.decl,
+                      compute_call_stmt_bb_frequency (id->dst_node->decl,
                                                       copy_basic_block),
                       CIF_ORIGINALLY_INDIRECT_CALL);
                  else
                    cgraph_create_edge (id->dst_node, dest, stmt,
                                        bb->count,
                                        compute_call_stmt_bb_frequency
-                                         (id->dst_node->symbol.decl,
+                                         (id->dst_node->decl,
                                           copy_basic_block))->inline_failed
                      = CIF_ORIGINALLY_INDIRECT_CALL;
                  if (dump_file)
@@@ -3739,7 -3745,7 +3743,7 @@@ estimate_num_insns (gimple stmt, eni_we
  
        /* Do not special case builtins where we see the body.
           This just confuse inliner.  */
-       if (!decl || !(node = cgraph_get_node (decl)) || node->symbol.definition)
+       if (!decl || !(node = cgraph_get_node (decl)) || node->definition)
          ;
        /* For buitins that are likely expanded to nothing or
           inlined do not account operand costs.  */
@@@ -4011,7 -4017,7 +4015,7 @@@ expand_call_inline (basic_block bb, gim
       If we cannot, then there is no hope of inlining the function.  */
    if (cg_edge->indirect_unknown_callee)
      goto egress;
-   fn = cg_edge->callee->symbol.decl;
+   fn = cg_edge->callee->decl;
    gcc_checking_assert (fn);
  
    /* If FN is a declaration of a function in a nested scope that was
        }
        goto egress;
      }
-   fn = cg_edge->callee->symbol.decl;
+   fn = cg_edge->callee->decl;
    cgraph_get_body (cg_edge->callee);
  
  #ifdef ENABLE_CHECKING
-   if (cg_edge->callee->symbol.decl != id->dst_node->symbol.decl)
+   if (cg_edge->callee->decl != id->dst_node->decl)
      verify_cgraph_node (cg_edge->callee);
  #endif
  
    id->eh_lp_nr = lookup_stmt_eh_lp (stmt);
  
    /* Update the callers EH personality.  */
-   if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->symbol.decl))
-     DECL_FUNCTION_PERSONALITY (cg_edge->caller->symbol.decl)
-       = DECL_FUNCTION_PERSONALITY (cg_edge->callee->symbol.decl);
+   if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl))
+     DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl)
+       = DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl);
  
    /* Split the block holding the GIMPLE_CALL.  */
    e = split_block (bb, stmt);
       variables in the function when the blocks get blown away as soon as we
       remove the cgraph node.  */
    if (gimple_block (stmt))
-     (*debug_hooks->outlining_inline_function) (cg_edge->callee->symbol.decl);
+     (*debug_hooks->outlining_inline_function) (cg_edge->callee->decl);
  
    /* Update callgraph if needed.  */
    cgraph_remove_node (cg_edge->callee);
@@@ -4485,7 -4491,7 +4489,7 @@@ optimize_inline_calls (tree fn
    memset (&id, 0, sizeof (id));
  
    id.src_node = id.dst_node = cgraph_get_node (fn);
-   gcc_assert (id.dst_node->symbol.definition);
+   gcc_assert (id.dst_node->definition);
    id.dst_fn = fn;
    /* Or any functions that aren't finished yet.  */
    if (current_function_decl)
@@@ -4585,10 -4591,6 +4589,6 @@@ copy_tree_r (tree *tp, int *walk_subtre
        /* Copy the node.  */
        new_tree = copy_node (*tp);
  
-       /* Propagate mudflap marked-ness.  */
-       if (flag_mudflap && mf_marked_p (*tp))
-         mf_mark (new_tree);
        *tp = new_tree;
  
        /* Now, restore the chain, if appropriate.  That will cause
        tree new_tree;
  
        new_tree = copy_node (*tp);
-       /* Propagate mudflap marked-ness.  */
-       if (flag_mudflap && mf_marked_p (*tp))
-         mf_mark (new_tree);
        CONSTRUCTOR_ELTS (new_tree) = vec_safe_copy (CONSTRUCTOR_ELTS (*tp));
        *tp = new_tree;
      }
@@@ -5080,7 -5077,7 +5075,7 @@@ delete_unreachable_blocks_update_callgr
              struct cgraph_edge *e;
              struct cgraph_node *node;
  
-             ipa_remove_stmt_references ((symtab_node)id->dst_node, gsi_stmt (bsi));
+             ipa_remove_stmt_references (id->dst_node, gsi_stmt (bsi));
  
              if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
                  &&(e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL)
                  && id->dst_node->clones)
                for (node = id->dst_node->clones; node != id->dst_node;)
                  {
-                   ipa_remove_stmt_references ((symtab_node)node, gsi_stmt (bsi));
+                   ipa_remove_stmt_references (node, gsi_stmt (bsi));
                    if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
                        && (e = cgraph_edge (node, gsi_stmt (bsi))) != NULL)
                      {
@@@ -5190,8 -5187,7 +5185,7 @@@ tree_function_versioning (tree old_decl
    unsigned i;
    struct ipa_replace_map *replace_info;
    basic_block old_entry_block, bb;
-   vec<gimple> init_stmts;
-   init_stmts.create (10);
+   stack_vec<gimple, 10> init_stmts;
    tree vars = NULL_TREE;
  
    gcc_assert (TREE_CODE (old_decl) == FUNCTION_DECL
    pointer_set_destroy (id.statements_to_fold);
    fold_cond_expr_cond ();
    delete_unreachable_blocks_update_callgraph (&id);
-   if (id.dst_node->symbol.definition)
+   if (id.dst_node->definition)
      cgraph_rebuild_references ();
    update_ssa (TODO_update_ssa);
  
    free_dominance_info (CDI_POST_DOMINATORS);
  
    gcc_assert (!id.debug_stmts.exists ());
-   init_stmts.release ();
    pop_cfun ();
    return;
  }
diff --combined gcc/tree-object-size.c
index ca21e92256ef8f0407d7f0c3249e9fb291239567,2d7ebfd764f009faa8a4bdc58d4a70f3e3fdc5f9..0b53f09f70811bbcacbd1c555f7c8864e2e7d2b8
@@@ -25,7 -25,10 +25,10 @@@ along with GCC; see the file COPYING3
  #include "tree.h"
  #include "diagnostic-core.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "bitmap.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-ssanames.h"
  #include "tree-pass.h"
  #include "tree-ssa-propagate.h"
  
@@@ -77,8 -80,8 +80,8 @@@ static unsigned HOST_WIDE_INT offset_li
  static void
  init_offset_limit (void)
  {
 -  if (host_integerp (TYPE_MAX_VALUE (sizetype), 1))
 -    offset_limit = tree_low_cst (TYPE_MAX_VALUE (sizetype), 1);
 +  if (tree_fits_uhwi_p (TYPE_MAX_VALUE (sizetype)))
 +    offset_limit = tree_to_uhwi (TYPE_MAX_VALUE (sizetype));
    else
      offset_limit = -1;
    offset_limit /= 2;
@@@ -106,7 -109,7 +109,7 @@@ compute_object_offset (const_tree expr
  
        t = TREE_OPERAND (expr, 1);
        off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
 -                      size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
 +                      size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
                                  / BITS_PER_UNIT));
        break;
  
  
      case MEM_REF:
        gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR);
 -      return double_int_to_tree (sizetype, mem_ref_offset (expr));
 +      return wide_int_to_tree (sizetype, mem_ref_offset (expr));
  
      default:
        return error_mark_node;
@@@ -191,10 -194,10 +194,10 @@@ addr_object_size (struct object_size_in
        }
        if (sz != unknown[object_size_type])
        {
 -        double_int dsz = double_int::from_uhwi (sz) - mem_ref_offset (pt_var);
 -        if (dsz.is_negative ())
 +        offset_int dsz = wi::sub (sz, mem_ref_offset (pt_var));
 +        if (wi::neg_p (dsz))
            sz = 0;
 -        else if (dsz.fits_uhwi ())
 +        else if (wi::fits_uhwi_p (dsz))
            sz = dsz.to_uhwi ();
          else
            sz = unknown[object_size_type];
      }
    else if (pt_var
           && DECL_P (pt_var)
 -         && host_integerp (DECL_SIZE_UNIT (pt_var), 1)
 +         && tree_fits_uhwi_p (DECL_SIZE_UNIT (pt_var))
           && (unsigned HOST_WIDE_INT)
 -              tree_low_cst (DECL_SIZE_UNIT (pt_var), 1) < offset_limit)
 +              tree_to_uhwi (DECL_SIZE_UNIT (pt_var)) < offset_limit)
      pt_var_size = DECL_SIZE_UNIT (pt_var);
    else if (pt_var
           && TREE_CODE (pt_var) == STRING_CST
           && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
 -         && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
 +         && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
           && (unsigned HOST_WIDE_INT)
 -            tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
 +            tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
              < offset_limit)
      pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
    else
          if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
            var = TREE_OPERAND (var, 0);
          if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
 -            || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
 +            || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var)))
              || (pt_var_size
                  && tree_int_cst_lt (pt_var_size,
                                      TYPE_SIZE_UNIT (TREE_TYPE (var)))))
    else
      bytes = pt_var_size;
  
 -  if (host_integerp (bytes, 1))
 -    return tree_low_cst (bytes, 1);
 +  if (tree_fits_uhwi_p (bytes))
 +    return tree_to_uhwi (bytes);
  
    return unknown[object_size_type];
  }
@@@ -398,9 -401,9 +401,9 @@@ alloc_object_size (const_gimple call, i
      {
        tree p = TREE_VALUE (alloc_size);
  
 -      arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
 +      arg1 = tree_to_hwi (TREE_VALUE (p))-1;
        if (TREE_CHAIN (p))
 -        arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
 +        arg2 = tree_to_hwi (TREE_VALUE (TREE_CHAIN (p)))-1;
      }
  
    if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
    else if (arg1 >= 0)
      bytes = fold_convert (sizetype, gimple_call_arg (call, arg1));
  
 -  if (bytes && host_integerp (bytes, 1))
 -    return tree_low_cst (bytes, 1);
 +  if (bytes && tree_fits_uhwi_p (bytes))
 +    return tree_to_uhwi (bytes);
  
    return unknown[object_size_type];
  }
@@@ -792,13 -795,13 +795,13 @@@ plus_stmt_object_size (struct object_si
        && (TREE_CODE (op0) == SSA_NAME
          || TREE_CODE (op0) == ADDR_EXPR))
      {
 -      if (! host_integerp (op1, 1))
 +      if (! tree_fits_uhwi_p (op1))
        bytes = unknown[object_size_type];
        else if (TREE_CODE (op0) == SSA_NAME)
 -      return merge_object_sizes (osi, var, op0, tree_low_cst (op1, 1));
 +      return merge_object_sizes (osi, var, op0, tree_to_uhwi (op1));
        else
        {
 -        unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
 +        unsigned HOST_WIDE_INT off = tree_to_uhwi (op1);
  
            /* op0 will be ADDR_EXPR here.  */
          bytes = addr_object_size (osi, op0, object_size_type);
@@@ -1224,10 -1227,10 +1227,10 @@@ compute_object_sizes (void
                {
                  tree ost = gimple_call_arg (call, 1);
  
 -                if (host_integerp (ost, 1))
 +                if (tree_fits_uhwi_p (ost))
                    {
                      unsigned HOST_WIDE_INT object_size_type
 -                      = tree_low_cst (ost, 1);
 +                      = tree_to_uhwi (ost);
  
                      if (object_size_type < 2)
                        result = fold_convert (size_type_node,
diff --combined gcc/tree-predcom.c
index ace59d3b2985f017ba751298af23c727bf775ca7,1005e783d0bf09700e4901750164128406cd1ee7..9a4898b8143490ecc8ff3bd4e47cbdcd109bcb4d
@@@ -191,6 -191,17 +191,17 @@@ along with GCC; see the file COPYING3
  #include "tree.h"
  #include "tm_p.h"
  #include "cfgloop.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-ivopts.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-into-ssa.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "ggc.h"
  #include "tree-data-ref.h"
  #include "tree-pass.h"
  #include "tree-affine.h"
  #include "tree-inline.h"
 +#include "wide-int-print.h"
  
  /* The maximum number of iterations between the considered memory
     references.  */
@@@ -229,7 -239,7 +240,7 @@@ typedef struct dref_
    unsigned distance;
  
    /* Number of iterations offset from the first reference in the component.  */
 -  double_int offset;
 +  widest_int offset;
  
    /* Number of the reference in a component, in dominance ordering.  */
    unsigned pos;
@@@ -345,7 -355,7 +356,7 @@@ dump_dref (FILE *file, dref ref
               DR_IS_READ (ref->ref) ? "" : ", write");
  
        fprintf (file, "      offset ");
 -      dump_double_int (file, ref->offset, false);
 +      print_decs (ref->offset, file);
        fprintf (file, "\n");
  
        fprintf (file, "      distance %u\n", ref->distance);
@@@ -618,7 -628,7 +629,7 @@@ aff_combination_dr_offset (struct data_
  
    tree_to_aff_combination_expand (DR_OFFSET (dr), type, offset,
                                  &name_expansions);
 -  aff_combination_const (&delta, type, tree_to_double_int (DR_INIT (dr)));
 +  aff_combination_const (&delta, type, wi::to_widest (DR_INIT (dr)));
    aff_combination_add (offset, &delta);
  }
  
  
  static bool
  determine_offset (struct data_reference *a, struct data_reference *b,
 -                double_int *off)
 +                widest_int *off)
  {
    aff_tree diff, baseb, step;
    tree typea, typeb;
      {
        /* If the references have loop invariant address, check that they access
         exactly the same location.  */
 -      *off = double_int_zero;
 +      *off = 0;
        return (operand_equal_p (DR_OFFSET (a), DR_OFFSET (b), 0)
              && operand_equal_p (DR_INIT (a), DR_INIT (b), 0));
      }
       is a multiple of step.  */
    aff_combination_dr_offset (a, &diff);
    aff_combination_dr_offset (b, &baseb);
 -  aff_combination_scale (&baseb, double_int_minus_one);
 +  aff_combination_scale (&baseb, -1);
    aff_combination_add (&diff, &baseb);
  
    tree_to_aff_combination_expand (DR_STEP (a), TREE_TYPE (DR_STEP (a)),
@@@ -734,7 -744,7 +745,7 @@@ split_data_refs_to_components (struct l
  
    FOR_EACH_VEC_ELT (depends, i, ddr)
      {
 -      double_int dummy_off;
 +      widest_int dummy_off;
  
        if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
        continue;
        dataref = XCNEW (struct dref_d);
        dataref->ref = dr;
        dataref->stmt = DR_STMT (dr);
 -      dataref->offset = double_int_zero;
 +      dataref->offset = 0;
        dataref->distance = 0;
  
        dataref->always_accessed
@@@ -833,7 -843,7 +844,7 @@@ suitable_component_p (struct loop *loop
    first = comp->refs[0];
    ok = suitable_reference_p (first->ref, &comp->comp_step);
    gcc_assert (ok);
 -  first->offset = double_int_zero;
 +  first->offset = 0;
  
    for (i = 1; comp->refs.iterate (i, &a); i++)
      {
@@@ -897,7 -907,7 +908,7 @@@ order_drefs (const void *a, const void 
  {
    const dref *const da = (const dref *) a;
    const dref *const db = (const dref *) b;
 -  int offcmp = (*da)->offset.scmp ((*db)->offset);
 +  int offcmp = wi::cmps ((*da)->offset, (*db)->offset);
  
    if (offcmp != 0)
      return offcmp;
@@@ -919,15 -929,16 +930,15 @@@ static voi
  add_ref_to_chain (chain_p chain, dref ref)
  {
    dref root = get_chain_root (chain);
 -  double_int dist;
  
 -  gcc_assert (root->offset.sle (ref->offset));
 -  dist = ref->offset - root->offset;
 -  if (double_int::from_uhwi (MAX_DISTANCE).ule (dist))
 +  gcc_assert (wi::les_p (root->offset, ref->offset));
 +  widest_int dist = ref->offset - root->offset;
 +  if (wi::leu_p (MAX_DISTANCE, dist))
      {
        free (ref);
        return;
      }
 -  gcc_assert (dist.fits_uhwi ());
 +  gcc_assert (wi::fits_uhwi_p (dist));
  
    chain->refs.safe_push (ref);
  
@@@ -1022,7 -1033,7 +1033,7 @@@ valid_initializer_p (struct data_refere
                     unsigned distance, struct data_reference *root)
  {
    aff_tree diff, base, step;
 -  double_int off;
 +  widest_int off;
  
    /* Both REF and ROOT must be accessing the same object.  */
    if (!operand_equal_p (DR_BASE_ADDRESS (ref), DR_BASE_ADDRESS (root), 0))
       -DISTANCE-th iteration.  */
    aff_combination_dr_offset (root, &diff);
    aff_combination_dr_offset (ref, &base);
 -  aff_combination_scale (&base, double_int_minus_one);
 +  aff_combination_scale (&base, -1);
    aff_combination_add (&diff, &base);
  
    tree_to_aff_combination_expand (DR_STEP (root), TREE_TYPE (DR_STEP (root)),
    if (!aff_combination_constant_multiple_p (&diff, &step, &off))
      return false;
  
 -  if (off != double_int::from_uhwi (distance))
 +  if (off != distance)
      return false;
  
    return true;
@@@ -1178,7 -1189,7 +1189,7 @@@ determine_roots_comp (struct loop *loop
    unsigned i;
    dref a;
    chain_p chain = NULL;
 -  double_int last_ofs = double_int_zero;
 +  widest_int last_ofs = 0;
  
    /* Invariants are handled specially.  */
    if (comp->comp_step == RS_INVARIANT)
    FOR_EACH_VEC_ELT (comp->refs, i, a)
      {
        if (!chain || DR_IS_WRITE (a->ref)
 -        || double_int::from_uhwi (MAX_DISTANCE).ule (a->offset - last_ofs))
 +        || wi::leu_p (MAX_DISTANCE, a->offset - last_ofs))
        {
          if (nontrivial_chain_p (chain))
            {
@@@ -2410,7 -2421,6 +2421,6 @@@ prepare_initializers (struct loop *loop
  static bool
  tree_predictive_commoning_loop (struct loop *loop)
  {
-   vec<loop_p> loop_nest;
    vec<data_reference_p> datarefs;
    vec<ddr_p> dependences;
    struct component *components;
  
    /* Find the data references and split them into components according to their
       dependence relations.  */
-   datarefs.create (10);
+   stack_vec<loop_p, 3> loop_nest;
    dependences.create (10);
-   loop_nest.create (3);
+   datarefs.create (10);
    if (! compute_data_dependences_for_loop (loop, true, &loop_nest, &datarefs,
                                           &dependences))
      {
        if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "Cannot analyze data dependencies\n");
-       loop_nest.release ();
        free_data_refs (datarefs);
        free_dependence_relations (dependences);
        return false;
diff --combined gcc/tree-pretty-print.c
index c88d0731acf0efcb8c33dd7274cdd9da5f16ecac,fe756339f6d420110222352b7b51092238f2f505..1d831ee24abf7ecc7d4896a57acf6362b84651cc
@@@ -25,14 -25,14 +25,15 @@@ along with GCC; see the file COPYING3
  #include "tree.h"
  #include "tree-pretty-print.h"
  #include "hashtab.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "cgraph.h"
  #include "langhooks.h"
  #include "tree-iterator.h"
  #include "tree-chrec.h"
  #include "dumpfile.h"
  #include "value-prof.h"
  #include "predict.h"
 +#include "wide-int-print.h"
  
  #include <new>                           // For placement-new.
  
@@@ -272,8 -272,8 +273,8 @@@ dump_array_domain (pretty_printer *buff
  
        if (min && max
          && integer_zerop (min)
 -        && host_integerp (max, 0))
 -      pp_wide_integer (buffer, TREE_INT_CST_LOW (max) + 1);
 +        && tree_fits_shwi_p (max))
 +      pp_wide_integer (buffer, tree_to_shwi (max) + 1);
        else
        {
          if (min)
@@@ -866,6 -866,7 +867,7 @@@ dump_generic_node (pretty_printer *buff
        break;
  
      case VOID_TYPE:
+     case POINTER_BOUNDS_TYPE:
      case INTEGER_TYPE:
      case REAL_TYPE:
      case FIXED_POINT_TYPE:
               NB: Neither of the following divisors can be trivially
               used to recover the original literal:
  
 -             TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (node)))
 +             tree_to_hwi (TYPE_SIZE_UNIT (TREE_TYPE (node)))
             TYPE_PRECISION (TREE_TYPE (TREE_TYPE (node)))  */
 -        pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
 +        pp_wide_integer (buffer, tree_to_hwi (node));
          pp_string (buffer, "B"); /* pseudo-unit */
        }
 +      else if (tree_fits_shwi_p (node))
 +      pp_wide_integer (buffer, tree_to_shwi (node));
 +      else if (tree_fits_uhwi_p (node))
 +      pp_unsigned_wide_integer (buffer, tree_to_uhwi (node));
        else
 -      pp_double_int (buffer, tree_to_double_int (node),
 -                     TYPE_UNSIGNED (TREE_TYPE (node)));
 +      {
 +        wide_int val = node;
 +
 +        if (wi::neg_p (val, TYPE_SIGN (TREE_TYPE (node))))
 +          {
 +            pp_minus (buffer);
 +            val = -val;
 +          }
 +        print_hex (val, pp_buffer (buffer)->digit_buffer);
 +        pp_string (buffer, pp_buffer (buffer)->digit_buffer);
 +      }
        if (TREE_OVERFLOW (node))
        pp_string (buffer, "(OVF)");
        break;
        tree field, val;
        bool is_struct_init = false;
        bool is_array_init = false;
 -      double_int curidx = double_int_zero;
 +      widest_int curidx;
        pp_left_brace (buffer);
        if (TREE_CLOBBER_P (node))
          pp_string (buffer, "CLOBBER");
          {
            tree minv = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (node)));
            is_array_init = true;
 -          curidx = tree_to_double_int (minv);
 +          curidx = wi::to_widest (minv);
          }
        FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (node), ix, field, val)
          {
                  }
                else if (is_array_init
                         && (TREE_CODE (field) != INTEGER_CST
 -                           || tree_to_double_int (field) != curidx))
 +                           || curidx != wi::to_widest (field)))
                  {
                    pp_left_bracket (buffer);
                    if (TREE_CODE (field) == RANGE_EXPR)
                        dump_generic_node (buffer, TREE_OPERAND (field, 1), spc,
                                           flags, false);
                        if (TREE_CODE (TREE_OPERAND (field, 1)) == INTEGER_CST)
 -                        curidx = tree_to_double_int (TREE_OPERAND (field, 1));
 +                        curidx = wi::to_widest (TREE_OPERAND (field, 1));
                      }
                    else
                      dump_generic_node (buffer, field, spc, flags, false);
                    if (TREE_CODE (field) == INTEGER_CST)
 -                    curidx = tree_to_double_int (field);
 +                    curidx = wi::to_widest (field);
                    pp_string (buffer, "]=");
                  }
              }
              if (is_array_init)
 -            curidx += double_int_one;
 +            curidx += 1;
            if (val && TREE_CODE (val) == ADDR_EXPR)
              if (TREE_CODE (TREE_OPERAND (val, 0)) == FUNCTION_DECL)
                val = TREE_OPERAND (val, 0);
        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);
        dump_block_node (buffer, node, spc, flags);
        break;
  
+     case CILK_SPAWN_STMT:
+       pp_string (buffer, "_Cilk_spawn ");
+       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+       break;
+     case CILK_SYNC_STMT:
+       pp_string (buffer, "_Cilk_sync");
+       break;
      default:
        NIY;
      }
@@@ -3390,7 -3399,7 +3413,7 @@@ dump_function_header (FILE *dump_file, 
      fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl));
    if (node)
      {
-       fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->symbol.order,
+       fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->order,
                 node->frequency == NODE_FREQUENCY_HOT
                 ? " (hot)"
                 : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
diff --combined gcc/tree-sra.c
index a4e6f629392e4cf06ee975113f13490fa477b7e2,38da57700e2de7e1ea23f45434dbc5a6b8ce2711..4f4d0a00648aef10143e2b17bac6dbb03616a4ae
@@@ -79,7 -79,13 +79,13 @@@ along with GCC; see the file COPYING3
  #include "tm.h"
  #include "tree.h"
  #include "gimple.h"
- #include "cgraph.h"
+ #include "bitmap.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "tree-pass.h"
  #include "ipa-prop.h"
@@@ -732,17 -738,17 +738,17 @@@ type_internals_preclude_sra_p (tree typ
                *msg = "zero structure field size";
                return true;
              }
 -          if (!host_integerp (DECL_FIELD_OFFSET (fld), 1))
 +          if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
              {
                *msg = "structure field offset not fixed";
                return true;
              }
 -          if (!host_integerp (DECL_SIZE (fld), 1))
 +          if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
              {
                *msg = "structure field size not fixed";
                return true;
              }
 -          if (!host_integerp (bit_position (fld), 0))
 +          if (!tree_fits_shwi_p (bit_position (fld)))
              {
                *msg = "structure field size too big";
                return true;
@@@ -979,7 -985,7 +985,7 @@@ completely_scalarize_record (tree base
            struct access *access;
            HOST_WIDE_INT size;
  
 -          size = tree_low_cst (DECL_SIZE (fld), 1);
 +          size = tree_to_uhwi (DECL_SIZE (fld));
            access = create_access_1 (base, pos, size);
            access->expr = nref;
            access->type = ft;
  static void
  completely_scalarize_var (tree var)
  {
 -  HOST_WIDE_INT size = tree_low_cst (DECL_SIZE (var), 1);
 +  HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (var));
    struct access *access;
  
    access = create_access_1 (var, 0, size);
@@@ -1360,11 -1366,11 +1366,11 @@@ compare_access_positions (const void *a
        return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
        /* Put any integral type with non-full precision last.  */
        else if (INTEGRAL_TYPE_P (f1->type)
 -             && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
 +             && (tree_to_hwi (TYPE_SIZE (f1->type))
                   != TYPE_PRECISION (f1->type)))
        return 1;
        else if (INTEGRAL_TYPE_P (f2->type)
 -             && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
 +             && (tree_to_hwi (TYPE_SIZE (f2->type))
                   != TYPE_PRECISION (f2->type)))
        return -1;
        /* Stabilize the sort.  */
@@@ -1426,7 -1432,7 +1432,7 @@@ make_fancy_name_1 (tree expr
        index = TREE_OPERAND (expr, 1);
        if (TREE_CODE (index) != INTEGER_CST)
        break;
 -      sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
 +      sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, tree_to_hwi (index));
        obstack_grow (&name_obstack, buffer, strlen (buffer));
        break;
  
        {
          obstack_1grow (&name_obstack, '$');
          sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
 -                 TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
 +                 tree_to_hwi (TREE_OPERAND (expr, 1)));
          obstack_grow (&name_obstack, buffer, strlen (buffer));
        }
        break;
@@@ -1641,14 -1647,14 +1647,14 @@@ build_user_friendly_ref_for_offset (tre
                continue;
  
              tr_pos = bit_position (fld);
 -            if (!tr_pos || !host_integerp (tr_pos, 1))
 +            if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
                continue;
 -            pos = TREE_INT_CST_LOW (tr_pos);
 +            pos = tree_to_uhwi (tr_pos);
              gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
              tr_size = DECL_SIZE (fld);
 -            if (!tr_size || !host_integerp (tr_size, 1))
 +            if (!tr_size || !tree_fits_uhwi_p (tr_size))
                continue;
 -            size = TREE_INT_CST_LOW (tr_size);
 +            size = tree_to_uhwi (tr_size);
              if (size == 0)
                {
                  if (pos != offset)
  
        case ARRAY_TYPE:
          tr_size = TYPE_SIZE (TREE_TYPE (type));
 -        if (!tr_size || !host_integerp (tr_size, 1))
 +        if (!tr_size || !tree_fits_uhwi_p (tr_size))
            return false;
 -        el_size = tree_low_cst (tr_size, 1);
 +        el_size = tree_to_uhwi (tr_size);
  
          minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
          if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
@@@ -1749,12 -1755,12 +1755,12 @@@ maybe_add_sra_candidate (tree var
        reject (var, "has incomplete type");
        return false;
      }
 -  if (!host_integerp (TYPE_SIZE (type), 1))
 +  if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
      {
        reject (var, "type size not fixed");
        return false;
      }
 -  if (tree_low_cst (TYPE_SIZE (type), 1) == 0)
 +  if (tree_to_uhwi (TYPE_SIZE (type)) == 0)
      {
        reject (var, "type size is zero");
        return false;
@@@ -2109,7 -2115,7 +2115,7 @@@ expr_with_var_bounded_array_refs_p (tre
    while (handled_component_p (expr))
      {
        if (TREE_CODE (expr) == ARRAY_REF
 -        && !host_integerp (array_ref_low_bound (expr), 0))
 +        && !tree_fits_shwi_p (array_ref_low_bound (expr)))
        return true;
        expr = TREE_OPERAND (expr, 0);
      }
@@@ -2478,7 -2484,7 +2484,7 @@@ analyze_all_variable_accesses (void
        if (TREE_CODE (var) == VAR_DECL
            && type_consists_of_records_p (TREE_TYPE (var)))
          {
 -          if ((unsigned) tree_low_cst (TYPE_SIZE (TREE_TYPE (var)), 1)
 +          if ((unsigned) tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var)))
                <= max_total_scalarization_size)
              {
                completely_scalarize_var (var);
@@@ -2789,12 -2795,12 +2795,12 @@@ sra_modify_expr (tree *expr, gimple_stm
      {
        HOST_WIDE_INT start_offset, chunk_size;
        if (bfr
 -        && host_integerp (TREE_OPERAND (bfr, 1), 1)
 -        && host_integerp (TREE_OPERAND (bfr, 2), 1))
 +        && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
 +        && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
        {
 -        chunk_size = tree_low_cst (TREE_OPERAND (bfr, 1), 1);
 +        chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
          start_offset = access->offset
 -          + tree_low_cst (TREE_OPERAND (bfr, 2), 1);
 +          + tree_to_uhwi (TREE_OPERAND (bfr, 2));
        }
        else
        start_offset = chunk_size = 0;
@@@ -3683,8 -3689,8 +3689,8 @@@ find_param_candidates (void
        continue;
  
        if (!COMPLETE_TYPE_P (type)
 -        || !host_integerp (TYPE_SIZE (type), 1)
 -          || tree_low_cst (TYPE_SIZE (type), 1) == 0
 +        || !tree_fits_uhwi_p (TYPE_SIZE (type))
 +          || tree_to_uhwi (TYPE_SIZE (type)) == 0
          || (AGGREGATE_TYPE_P (type)
              && type_internals_preclude_sra_p (type, &msg)))
        continue;
@@@ -4057,9 -4063,9 +4063,9 @@@ splice_param_accesses (tree parm, bool 
      }
  
    if (POINTER_TYPE_P (TREE_TYPE (parm)))
 -    agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))), 1);
 +    agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
    else
 -    agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (parm)), 1);
 +    agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
    if (total_size >= agg_size)
      return NULL;
  
@@@ -4078,13 -4084,13 +4084,13 @@@ decide_one_param_reduction (struct acce
    tree parm;
  
    parm = repr->base;
 -  cur_parm_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (parm)), 1);
 +  cur_parm_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm)));
    gcc_assert (cur_parm_size > 0);
  
    if (POINTER_TYPE_P (TREE_TYPE (parm)))
      {
        by_ref = true;
 -      agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))), 1);
 +      agg_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))));
      }
    else
      {
@@@ -4511,7 -4517,7 +4517,7 @@@ sra_ipa_modify_expr (tree *expr, bool c
  
    if (TREE_CODE (base) == MEM_REF)
      {
 -      offset += mem_ref_offset (base).low * BITS_PER_UNIT;
 +      offset += mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT;
        base = TREE_OPERAND (base, 0);
      }
  
@@@ -4832,14 -4838,14 +4838,14 @@@ convert_callers_for_node (struct cgraph
  
    for (cs = node->callers; cs; cs = cs->next_caller)
      {
-       push_cfun (DECL_STRUCT_FUNCTION (cs->caller->symbol.decl));
+       push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
  
        if (dump_file)
        fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n",
                 xstrdup (cgraph_node_name (cs->caller)),
-                cs->caller->symbol.order,
+                cs->caller->order,
                 xstrdup (cgraph_node_name (cs->callee)),
-                cs->callee->symbol.order);
+                cs->callee->order);
  
        ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
  
  
    for (cs = node->callers; cs; cs = cs->next_caller)
      if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
-       && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->symbol.decl)))
+       && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
        compute_inline_parameters (cs->caller, true);
    BITMAP_FREE (recomputed_callers);
  
@@@ -4884,7 -4890,7 +4890,7 @@@ convert_callers (struct cgraph_node *no
            {
              if (dump_file)
                fprintf (dump_file, "Adjusting recursive call");
-             gimple_call_set_fndecl (stmt, node->symbol.decl);
+             gimple_call_set_fndecl (stmt, node->decl);
              ipa_modify_call_arguments (NULL, stmt, adjustments);
            }
        }
@@@ -4912,11 -4918,11 +4918,11 @@@ modify_function (struct cgraph_node *no
                                         NULL, false, NULL, NULL, "isra");
    redirect_callers.release ();
  
-   push_cfun (DECL_STRUCT_FUNCTION (new_node->symbol.decl));
+   push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
    ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
    cfg_changed = ipa_sra_modify_function_body (adjustments);
    sra_ipa_reset_debug_stmts (adjustments);
-   convert_callers (new_node, node->symbol.decl, adjustments);
+   convert_callers (new_node, node->decl, adjustments);
    cgraph_make_node_local (new_node);
    return cfg_changed;
  }
@@@ -4952,7 -4958,7 +4958,7 @@@ ipa_sra_preliminary_function_checks (st
        return false;
      }
  
-   if (!tree_versionable_function_p (node->symbol.decl))
+   if (!tree_versionable_function_p (node->decl))
      {
        if (dump_file)
        fprintf (dump_file, "Function is not versionable.\n");
        return false;
      }
  
-   if ((DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
+   if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
        && inline_summary (node)->size >= MAX_INLINE_INSNS_AUTO)
      {
        if (dump_file)
        return false;
      }
  
-   if (TYPE_ATTRIBUTES (TREE_TYPE (node->symbol.decl)))
+   if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
      return false;
  
    return true;
diff --combined gcc/tree-ssa-address.c
index 0d587896896f1225b5084730b9deb18e4ec13cc4,146f909c7b1fa4613ba6977345854e6cc44b0710..d97f7bbdf7a5d05ee9eda6bfb15714d8749b5c9c
@@@ -28,7 -28,10 +28,10 @@@ along with GCC; see the file COPYING3
  #include "tm_p.h"
  #include "basic-block.h"
  #include "tree-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-ivopts.h"
+ #include "tree-dfa.h"
  #include "dumpfile.h"
  #include "flags.h"
  #include "tree-inline.h"
@@@ -197,15 -200,15 +200,15 @@@ addr_for_mem_ref (struct mem_address *a
    struct mem_addr_template *templ;
  
    if (addr->step && !integer_onep (addr->step))
 -    st = immed_double_int_const (tree_to_double_int (addr->step), pointer_mode);
 +    st = immed_wide_int_const (wide_int (addr->step), pointer_mode);
    else
      st = NULL_RTX;
  
    if (addr->offset && !integer_zerop (addr->offset))
 -    off = immed_double_int_const
 -          (tree_to_double_int (addr->offset)
 -           .sext (TYPE_PRECISION (TREE_TYPE (addr->offset))),
 -           pointer_mode);
 +    {
 +      offset_int dc = offset_int::from (addr->offset, SIGNED);
 +      off = immed_wide_int_const (dc, pointer_mode);
 +    }
    else
      off = NULL_RTX;
  
@@@ -413,7 -416,7 +416,7 @@@ move_fixed_address_to_symbol (struct me
  
    for (i = 0; i < addr->n; i++)
      {
 -      if (!addr->elts[i].coef.is_one ())
 +      if (addr->elts[i].coef != 1)
        continue;
  
        val = addr->elts[i].val;
@@@ -441,7 -444,7 +444,7 @@@ move_hint_to_base (tree type, struct me
  
    for (i = 0; i < addr->n; i++)
      {
 -      if (!addr->elts[i].coef.is_one ())
 +      if (addr->elts[i].coef != 1)
        continue;
  
        val = addr->elts[i].val;
@@@ -473,7 -476,7 +476,7 @@@ move_pointer_to_base (struct mem_addres
  
    for (i = 0; i < addr->n; i++)
      {
 -      if (!addr->elts[i].coef.is_one ())
 +      if (addr->elts[i].coef != 1)
        continue;
  
        val = addr->elts[i].val;
@@@ -509,7 -512,7 +512,7 @@@ move_variant_to_index (struct mem_addre
      return;
  
    parts->index = fold_convert (sizetype, val);
 -  parts->step = double_int_to_tree (sizetype, addr->elts[i].coef);
 +  parts->step = wide_int_to_tree (sizetype, addr->elts[i].coef);
    aff_combination_remove_elt (addr, i);
  }
  
@@@ -552,15 -555,16 +555,15 @@@ most_expensive_mult_to_index (tree type
    addr_space_t as = TYPE_ADDR_SPACE (type);
    enum machine_mode address_mode = targetm.addr_space.address_mode (as);
    HOST_WIDE_INT coef;
 -  double_int best_mult, amult, amult_neg;
    unsigned best_mult_cost = 0, acost;
    tree mult_elt = NULL_TREE, elt;
    unsigned i, j;
    enum tree_code op_code;
  
 -  best_mult = double_int_zero;
 +  offset_int best_mult = 0;
    for (i = 0; i < addr->n; i++)
      {
 -      if (!addr->elts[i].coef.fits_shwi ())
 +      if (!wi::fits_shwi_p (addr->elts[i].coef))
        continue;
  
        coef = addr->elts[i].coef.to_shwi ();
        if (acost > best_mult_cost)
        {
          best_mult_cost = acost;
 -        best_mult = addr->elts[i].coef;
 +        best_mult = offset_int::from (addr->elts[i].coef, SIGNED);
        }
      }
  
    /* Collect elements multiplied by best_mult.  */
    for (i = j = 0; i < addr->n; i++)
      {
 -      amult = addr->elts[i].coef;
 -      amult_neg = double_int_ext_for_comb (-amult, addr);
 +      offset_int amult = offset_int::from (addr->elts[i].coef, SIGNED);
 +      offset_int amult_neg = -wi::sext (amult, TYPE_PRECISION (addr->type));
  
        if (amult == best_mult)
        op_code = PLUS_EXPR;
    addr->n = j;
  
    parts->index = mult_elt;
 -  parts->step = double_int_to_tree (sizetype, best_mult);
 +  parts->step = wide_int_to_tree (sizetype, best_mult);
  }
  
  /* Splits address ADDR for a memory access of type TYPE into PARTS.
@@@ -636,8 -640,8 +639,8 @@@ addr_to_parts (tree type, aff_tree *add
    parts->index = NULL_TREE;
    parts->step = NULL_TREE;
  
 -  if (!addr->offset.is_zero ())
 -    parts->offset = double_int_to_tree (sizetype, addr->offset);
 +  if (addr->offset != 0)
 +    parts->offset = wide_int_to_tree (sizetype, addr->offset);
    else
      parts->offset = NULL_TREE;
  
    for (i = 0; i < addr->n; i++)
      {
        part = fold_convert (sizetype, addr->elts[i].val);
 -      if (!addr->elts[i].coef.is_one ())
 +      if (addr->elts[i].coef != 1)
        part = fold_build2 (MULT_EXPR, sizetype, part,
 -                          double_int_to_tree (sizetype, addr->elts[i].coef));
 +                          wide_int_to_tree (sizetype, addr->elts[i].coef));
        add_to_parts (parts, part);
      }
    if (addr->rest)
@@@ -875,11 -879,11 +878,11 @@@ copy_ref_info (tree new_ref, tree old_r
              && !(TREE_CODE (new_ref) == TARGET_MEM_REF
                   && (TMR_INDEX2 (new_ref)
                       || (TMR_STEP (new_ref)
 -                         && (TREE_INT_CST_LOW (TMR_STEP (new_ref))
 +                         && (tree_to_hwi (TMR_STEP (new_ref))
                               < align)))))
            {
 -            unsigned int inc = (mem_ref_offset (old_ref)
 -                                - mem_ref_offset (new_ref)).low;
 +            unsigned int inc = mem_ref_offset (old_ref).to_uhwi ()
 +                                - mem_ref_offset (new_ref).to_uhwi ();
              adjust_ptr_info_misalignment (new_pi, inc);
            }
          else
diff --combined gcc/tree-ssa-alias.c
index 5e80e66479c0ec05351c69c26d57100036da4348,efc08c20991973d7ffe0e49de9435cb398664c33..1a58ce722ed4593009d82789de169e10a7058528
@@@ -34,11 -34,12 +34,12 @@@ along with GCC; see the file COPYING3
  #include "tree-pretty-print.h"
  #include "dumpfile.h"
  #include "gimple.h"
- #include "tree-ssa.h"
+ #include "gimple-ssa.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "tree-inline.h"
  #include "params.h"
  #include "vec.h"
- #include "bitmap.h"
  #include "pointer-set.h"
  #include "alloc-pool.h"
  #include "tree-ssa-alias.h"
@@@ -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;
@@@ -727,11 -746,8 +745,8 @@@ aliasing_component_refs_p (tree ref1
  static bool
  nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
  {
-   vec<tree, va_stack> component_refs1;
-   vec<tree, va_stack> component_refs2;
-   vec_stack_alloc (tree, component_refs1, 16);
-   vec_stack_alloc (tree, component_refs2, 16);
+   stack_vec<tree, 16> component_refs1;
+   stack_vec<tree, 16> component_refs2;
  
    /* Create the stack of handled components for REF1.  */
    while (handled_component_p (ref1))
@@@ -874,6 -890,7 +889,6 @@@ indirect_ref_may_alias_decl_p (tree ref
    tree ptrtype1, dbase2;
    HOST_WIDE_INT offset1p = offset1, offset2p = offset2;
    HOST_WIDE_INT doffset1, doffset2;
 -  double_int moff;
  
    gcc_checking_assert ((TREE_CODE (base1) == MEM_REF
                        || TREE_CODE (base1) == TARGET_MEM_REF)
  
    /* The offset embedded in MEM_REFs can be negative.  Bias them
       so that the resulting offset adjustment is positive.  */
 -  moff = mem_ref_offset (base1);
 -  moff = moff.lshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT));
 -  if (moff.is_negative ())
 -    offset2p += (-moff).low;
 +  offset_int moff = mem_ref_offset (base1);
 +  moff = wi::lshift (moff, (BITS_PER_UNIT == 8
 +                          ? 3 : exact_log2 (BITS_PER_UNIT)));
 +  if (wi::neg_p (moff))
 +    offset2p += (-moff).to_short_addr ();
    else
 -    offset1p += moff.low;
 +    offset1p += moff.to_short_addr ();
  
    /* If only one reference is based on a variable, they cannot alias if
       the pointer access is beyond the extent of the variable access.
    if (TREE_CODE (dbase2) == MEM_REF
        || TREE_CODE (dbase2) == TARGET_MEM_REF)
      {
 -      double_int moff = mem_ref_offset (dbase2);
 -      moff = moff.lshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT));
 -      if (moff.is_negative ())
 -      doffset1 -= (-moff).low;
 +      offset_int moff = mem_ref_offset (dbase2);
 +      moff = wi::lshift (moff, (BITS_PER_UNIT == 8
 +                              ? 3 : exact_log2 (BITS_PER_UNIT)));
 +      if (wi::neg_p (moff))
 +      doffset1 -= (-moff).to_short_addr ();
        else
 -      doffset2 -= moff.low;
 +      doffset2 -= moff.to_short_addr ();
      }
  
    /* If either reference is view-converted, give up now.  */
@@@ -1052,23 -1067,21 +1067,23 @@@ indirect_refs_may_alias_p (tree ref1 AT
                      && operand_equal_p (TMR_INDEX2 (base1),
                                          TMR_INDEX2 (base2), 0))))))
      {
 -      double_int moff;
 +      offset_int moff;
        /* The offset embedded in MEM_REFs can be negative.  Bias them
         so that the resulting offset adjustment is positive.  */
        moff = mem_ref_offset (base1);
 -      moff = moff.lshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT));
 -      if (moff.is_negative ())
 -      offset2 += (-moff).low;
 +      moff = wi::lshift (moff, (BITS_PER_UNIT == 8
 +                              ? 3 : exact_log2 (BITS_PER_UNIT)));
 +      if (wi::neg_p (moff))
 +      offset2 += (-moff).to_short_addr ();
        else
 -      offset1 += moff.low;
 +      offset1 += moff.to_shwi ();
        moff = mem_ref_offset (base2);
 -      moff = moff.lshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT));
 -      if (moff.is_negative ())
 -      offset1 += (-moff).low;
 +      moff = wi::lshift (moff, (BITS_PER_UNIT == 8
 +                              ? 3 : exact_log2 (BITS_PER_UNIT)));
 +      if (wi::neg_p (moff))
 +      offset1 += (-moff).to_short_addr ();
        else
 -      offset2 += moff.low;
 +      offset2 += moff.to_short_addr ();
        return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
      }
    if (!ptr_derefs_may_alias_p (ptr1, ptr2))
@@@ -2017,15 -2030,15 +2032,15 @@@ stmt_kills_ref_p_1 (gimple stmt, ao_re
              if (!tree_int_cst_equal (TREE_OPERAND (base, 1),
                                       TREE_OPERAND (ref->base, 1)))
                {
 -                double_int off1 = mem_ref_offset (base);
 -                off1 = off1.lshift (BITS_PER_UNIT == 8
 -                                    ? 3 : exact_log2 (BITS_PER_UNIT));
 -                off1 = off1 + double_int::from_shwi (offset);
 -                double_int off2 = mem_ref_offset (ref->base);
 -                off2 = off2.lshift (BITS_PER_UNIT == 8
 -                                    ? 3 : exact_log2 (BITS_PER_UNIT));
 -                off2 = off2 + double_int::from_shwi (ref_offset);
 -                if (off1.fits_shwi () && off2.fits_shwi ())
 +                offset_int off1 = mem_ref_offset (base);
 +                off1 = wi::lshift (off1, (BITS_PER_UNIT == 8
 +                                          ? 3 : exact_log2 (BITS_PER_UNIT)));
 +                off1 += offset;
 +                offset_int off2 = mem_ref_offset (ref->base);
 +                off2 = wi::lshift (off2, (BITS_PER_UNIT == 8
 +                                          ? 3 : exact_log2 (BITS_PER_UNIT)));
 +                off2 += ref_offset;
 +                if (wi::fits_shwi_p (off1) && wi::fits_shwi_p (off2))
                    {
                      offset = off1.to_shwi ();
                      ref_offset = off2.to_shwi ();
          && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
        switch (DECL_FUNCTION_CODE (callee))
          {
+         case BUILT_IN_FREE:
+           {
+             tree ptr = gimple_call_arg (stmt, 0);
+             tree base = ao_ref_base (ref);
+             if (base && TREE_CODE (base) == MEM_REF
+                 && TREE_OPERAND (base, 0) == ptr)
+               return true;
+             break;
+           }
          case BUILT_IN_MEMCPY:
          case BUILT_IN_MEMPCPY:
          case BUILT_IN_MEMMOVE:
              tree len = gimple_call_arg (stmt, 2);
              tree base = NULL_TREE;
              HOST_WIDE_INT offset = 0;
 -            if (!host_integerp (len, 0))
 +            if (!tree_fits_shwi_p (len))
                return false;
              if (TREE_CODE (dest) == ADDR_EXPR)
                base = get_addr_base_and_unit_offset (TREE_OPERAND (dest, 0),
              if (base
                  && base == ao_ref_base (ref))
                {
 -                HOST_WIDE_INT size = TREE_INT_CST_LOW (len);
 +                HOST_WIDE_INT size = tree_to_hwi (len);
                  if (offset <= ref->offset / BITS_PER_UNIT
                      && (offset + size
                          >= ((ref->offset + ref->max_size + BITS_PER_UNIT - 1)
diff --combined gcc/tree-ssa-ccp.c
index 202703b20529e8cb45fa68f32837d4bb804dc170,5b6c0dbea28adfb1cbdf1a7758ffb2fbfec7b960..1c86bf93e9a719af0b8e92494cc89f5c23dc08bb
@@@ -98,15 -98,6 +98,15 @@@ along with GCC; see the file COPYING3
     array CONST_VAL[i].VALUE.  That is fed into substitute_and_fold for
     final substitution and folding.
  
 +   This algorithm uses wide-ints at the max precision of the target.
 +   This means that, with one uninteresting exception, variables with
 +   UNSIGNED types never go to VARYING because the bits above the
 +   precision of the type of the variable are always zero.  The
 +   uninteresting case is a variable of UNSIGNED type that has the
 +   maximum precision of the target.  Such variables can go to VARYING,
 +   but this causes no loss of infomation since these variables will
 +   never be extended.
 +
     References:
  
       Constant propagation with conditional branches,
  #include "basic-block.h"
  #include "function.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
  #include "tree-pass.h"
  #include "tree-ssa-propagate.h"
  #include "value-prof.h"
  #include "dbgcnt.h"
  #include "params.h"
  #include "hash-table.h"
 -
 +#include "wide-int-print.h"
  
  /* Possible lattice values.  */
  typedef enum
@@@ -156,11 -152,9 +161,11 @@@ struct prop_value_d 
      /* Propagated value.  */
      tree value;
  
 -    /* Mask that applies to the propagated value during CCP.  For
 -       X with a CONSTANT lattice value X & ~mask == value & ~mask.  */
 -    double_int mask;
 +    /* Mask that applies to the propagated value during CCP.  For X
 +       with a CONSTANT lattice value X & ~mask == value & ~mask.  The
 +       zero bits in the mask cover constant values.  The ones mean no
 +       information.  */
 +    widest_int mask;
  };
  
  typedef struct prop_value_d prop_value_t;
@@@ -195,19 -189,18 +200,19 @@@ dump_lattice_value (FILE *outf, const c
        break;
      case CONSTANT:
        if (TREE_CODE (val.value) != INTEGER_CST
 -        || val.mask.is_zero ())
 +        || val.mask == 0)
        {
          fprintf (outf, "%sCONSTANT ", prefix);
          print_generic_expr (outf, val.value, dump_flags);
        }
        else
        {
 -        double_int cval = tree_to_double_int (val.value).and_not (val.mask);
 -        fprintf (outf, "%sCONSTANT " HOST_WIDE_INT_PRINT_DOUBLE_HEX,
 -                 prefix, cval.high, cval.low);
 -        fprintf (outf, " (" HOST_WIDE_INT_PRINT_DOUBLE_HEX ")",
 -                 val.mask.high, val.mask.low);
 +        wide_int cval = wi::bit_and_not (wi::to_widest (val.value), val.mask);
 +        fprintf (outf, "%sCONSTANT ", prefix);
 +        print_hex (cval, outf);
 +        fprintf (outf, " (");
 +        print_hex (val.mask, outf);
 +        fprintf (outf, ")");
        }
        break;
      default:
@@@ -249,7 -242,7 +254,7 @@@ debug_lattice_value (prop_value_t val
  static prop_value_t
  get_default_value (tree var)
  {
 -  prop_value_t val = { UNINITIALIZED, NULL_TREE, { 0, 0 } };
 +  prop_value_t val = { UNINITIALIZED, NULL_TREE, 0 };
    gimple stmt;
  
    stmt = SSA_NAME_DEF_STMT (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))
      {
        /* Otherwise, VAR will never take on a constant value.  */
        val.lattice_val = VARYING;
 -      val.mask = double_int_minus_one;
 +      val.mask = -1;
      }
  
    return val;
@@@ -341,7 -347,7 +359,7 @@@ get_constant_value (tree var
    if (val
        && val->lattice_val == CONSTANT
        && (TREE_CODE (val->value) != INTEGER_CST
 -        || val->mask.is_zero ()))
 +        || val->mask == 0))
      return val->value;
    return NULL_TREE;
  }
@@@ -355,7 -361,7 +373,7 @@@ set_value_varying (tree var
  
    val->lattice_val = VARYING;
    val->value = NULL_TREE;
 -  val->mask = double_int_minus_one;
 +  val->mask = -1;
  }
  
  /* For float types, modify the value of VAL to make ccp work correctly
@@@ -432,8 -438,8 +450,8 @@@ valid_lattice_transition (prop_value_t 
    /* Bit-lattices have to agree in the still valid bits.  */
    if (TREE_CODE (old_val.value) == INTEGER_CST
        && TREE_CODE (new_val.value) == INTEGER_CST)
 -    return tree_to_double_int (old_val.value).and_not (new_val.mask)
 -         == tree_to_double_int (new_val.value).and_not (new_val.mask);
 +    return (wi::bit_and_not (wi::to_widest (old_val.value), new_val.mask)
 +          == wi::bit_and_not (wi::to_widest (new_val.value), new_val.mask));
  
    /* Otherwise constant values have to agree.  */
    return operand_equal_p (old_val.value, new_val.value, 0);
@@@ -458,8 -464,9 +476,8 @@@ set_lattice_value (tree var, prop_value
        && TREE_CODE (new_val.value) == INTEGER_CST
        && TREE_CODE (old_val->value) == INTEGER_CST)
      {
 -      double_int diff;
 -      diff = tree_to_double_int (new_val.value)
 -           ^ tree_to_double_int (old_val->value);
 +      widest_int diff = (wi::to_widest (new_val.value)
 +                       ^ wi::to_widest (old_val->value));
        new_val.mask = new_val.mask | old_val->mask | diff;
      }
  
        || (new_val.lattice_val == CONSTANT
          && TREE_CODE (new_val.value) == INTEGER_CST
          && (TREE_CODE (old_val->value) != INTEGER_CST
 -            || new_val.mask != old_val->mask)))
 +            || new_val.mask 
 +            != old_val->mask)))
      {
        /* ???  We would like to delay creation of INTEGER_CSTs from
         partially constants here.  */
  
  static prop_value_t get_value_for_expr (tree, bool);
  static prop_value_t bit_value_binop (enum tree_code, tree, tree, tree);
 -static void bit_value_binop_1 (enum tree_code, tree, double_int *, double_int *,
 -                             tree, double_int, double_int,
 -                             tree, double_int, double_int);
 +static void bit_value_binop_1 (enum tree_code, tree, widest_int *, widest_int *,
 +                             tree, widest_int, widest_int,
 +                             tree, widest_int, widest_int);
  
 -/* Return a double_int that can be used for bitwise simplifications
 +/* Return a widest_int that can be used for bitwise simplifications
     from VAL.  */
  
 -static double_int
 -value_to_double_int (prop_value_t val)
 +static widest_int
 +value_to_wide_int (prop_value_t val)
  {
    if (val.value
        && TREE_CODE (val.value) == INTEGER_CST)
 -    return tree_to_double_int (val.value);
 -  else
 -    return double_int_zero;
 +    return wi::to_widest (val.value);
 +
 +  return 0;
  }
  
  /* Return the value for the address expression EXPR based on alignment
@@@ -526,11 -532,14 +544,11 @@@ get_value_from_alignment (tree expr
  
    get_pointer_alignment_1 (expr, &align, &bitpos);
    val.mask = (POINTER_TYPE_P (type) || TYPE_UNSIGNED (type)
 -            ? double_int::mask (TYPE_PRECISION (type))
 -            : double_int_minus_one)
 -           .and_not (double_int::from_uhwi (align / BITS_PER_UNIT - 1));
 -  val.lattice_val = val.mask.is_minus_one () ? VARYING : CONSTANT;
 +            ? wi::mask <widest_int> (TYPE_PRECISION (type), false)
 +            : -1).and_not (align / BITS_PER_UNIT - 1);
 +  val.lattice_val = val.mask == -1 ? VARYING : CONSTANT;
    if (val.lattice_val == CONSTANT)
 -    val.value
 -      = double_int_to_tree (type,
 -                          double_int::from_uhwi (bitpos / BITS_PER_UNIT));
 +    val.value = build_int_cstu (type, bitpos / BITS_PER_UNIT);
    else
      val.value = NULL_TREE;
  
@@@ -559,7 -568,7 +577,7 @@@ get_value_for_expr (tree expr, bool for
      {
        val.lattice_val = CONSTANT;
        val.value = expr;
 -      val.mask = double_int_zero;
 +      val.mask = 0;
        canonicalize_float_value (&val);
      }
    else if (TREE_CODE (expr) == ADDR_EXPR)
    else
      {
        val.lattice_val = VARYING;
 -      val.mask = double_int_minus_one;
 +      val.mask = 1;
        val.value = NULL_TREE;
      }
    return val;
@@@ -811,7 -820,7 +829,7 @@@ do_dbg_cnt (void
        if (!dbg_cnt (ccp))
          {
            const_val[i].lattice_val = VARYING;
 -        const_val[i].mask = double_int_minus_one;
 +        const_val[i].mask = -1;
            const_val[i].value = NULL_TREE;
          }
      }
@@@ -832,7 -841,8 +850,8 @@@ ccp_finalize (void
    do_dbg_cnt ();
  
    /* Derive alignment and misalignment information from partially
-      constant pointers in the lattice.  */
+      constant pointers in the lattice or nonzero bits from partially
+      constant integers.  */
    for (i = 1; i < num_ssa_names; ++i)
      {
        tree name = ssa_name (i);
        unsigned int tem, align;
  
        if (!name
-         || !POINTER_TYPE_P (TREE_TYPE (name)))
+         || (!POINTER_TYPE_P (TREE_TYPE (name))
+             && (!INTEGRAL_TYPE_P (TREE_TYPE (name))
+                 /* Don't record nonzero bits before IPA to avoid
+                    using too much memory.  */
+                 || first_pass_instance)))
        continue;
  
        val = get_value (name);
          || 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.  */
@@@ -895,7 -920,7 +929,7 @@@ ccp_lattice_meet (prop_value_t *val1, p
      {
        /* any M VARYING = VARYING.  */
        val1->lattice_val = VARYING;
 -      val1->mask = double_int_minus_one;
 +      val1->mask = -1;
        val1->value = NULL_TREE;
      }
    else if (val1->lattice_val == CONSTANT
  
           For INTEGER_CSTs mask unequal bits.  If no equal bits remain,
         drop to varying.  */
 -      val1->mask = val1->mask | val2->mask
 -                 | (tree_to_double_int (val1->value)
 -                    ^ tree_to_double_int (val2->value));
 -      if (val1->mask.is_minus_one ())
 +      val1->mask = (val1->mask | val2->mask
 +                  | (wi::to_widest (val1->value)
 +                     ^ wi::to_widest (val2->value)));
 +      if (val1->mask == -1)
        {
          val1->lattice_val = VARYING;
          val1->value = NULL_TREE;
      {
        /* Any other combination is VARYING.  */
        val1->lattice_val = VARYING;
 -      val1->mask = double_int_minus_one;
 +      val1->mask = -1;
        val1->value = NULL_TREE;
      }
  }
@@@ -1099,8 -1124,8 +1133,8 @@@ ccp_fold (gimple stmt
  
  static void
  bit_value_unop_1 (enum tree_code code, tree type,
 -                double_int *val, double_int *mask,
 -                tree rtype, double_int rval, double_int rmask)
 +                widest_int *val, widest_int *mask,
 +                tree rtype, const widest_int &rval, const widest_int &rmask)
  {
    switch (code)
      {
  
      case NEGATE_EXPR:
        {
 -      double_int temv, temm;
 +      widest_int temv, temm;
        /* Return ~rval + 1.  */
        bit_value_unop_1 (BIT_NOT_EXPR, type, &temv, &temm, type, rval, rmask);
        bit_value_binop_1 (PLUS_EXPR, type, val, mask,
 -                       type, temv, temm,
 -                       type, double_int_one, double_int_zero);
 +                         type, temv, temm, type, 1, 0);
        break;
        }
  
      CASE_CONVERT:
        {
 -      bool uns;
 +      signop sgn;
  
        /* First extend mask and value according to the original type.  */
 -      uns = TYPE_UNSIGNED (rtype);
 -      *mask = rmask.ext (TYPE_PRECISION (rtype), uns);
 -      *val = rval.ext (TYPE_PRECISION (rtype), uns);
 +      sgn = TYPE_SIGN (rtype);
 +      *mask = wi::ext (rmask, TYPE_PRECISION (rtype), sgn);
 +      *val = wi::ext (rval, TYPE_PRECISION (rtype), sgn);
  
        /* Then extend mask and value according to the target type.  */
 -      uns = TYPE_UNSIGNED (type);
 -      *mask = (*mask).ext (TYPE_PRECISION (type), uns);
 -      *val = (*val).ext (TYPE_PRECISION (type), uns);
 +      sgn = TYPE_SIGN (type);
 +      *mask = wi::ext (*mask, TYPE_PRECISION (type), sgn);
 +      *val = wi::ext (*val, TYPE_PRECISION (type), sgn);
        break;
        }
  
      default:
 -      *mask = double_int_minus_one;
 +      *mask = -1;
        break;
      }
  }
  
  static void
  bit_value_binop_1 (enum tree_code code, tree type,
 -                 double_int *val, double_int *mask,
 -                 tree r1type, double_int r1val, double_int r1mask,
 -                 tree r2type, double_int r2val, double_int r2mask)
 +                 widest_int *val, widest_int *mask,
 +                 tree r1type, widest_int r1val, widest_int r1mask,
 +                 tree r2type, widest_int r2val, widest_int r2mask)
  {
 -  bool uns = TYPE_UNSIGNED (type);
 -  /* Assume we'll get a constant result.  Use an initial varying value,
 -     we fall back to varying in the end if necessary.  */
 -  *mask = double_int_minus_one;
 +  signop sgn = TYPE_SIGN (type);
 +  int width = TYPE_PRECISION (type);
 +
 +  /* Assume we'll get a constant result.  Use an initial non varying
 +     value, we fall back to varying in the end if necessary.  */
 +  *mask = -1;
 +
    switch (code)
      {
      case BIT_AND_EXPR:
  
      case LROTATE_EXPR:
      case RROTATE_EXPR:
 -      if (r2mask.is_zero ())
 +      if (r2mask == 0)
        {
 -        HOST_WIDE_INT shift = r2val.low;
 -        if (code == RROTATE_EXPR)
 -          shift = -shift;
 -        *mask = r1mask.lrotate (shift, TYPE_PRECISION (type));
 -        *val = r1val.lrotate (shift, TYPE_PRECISION (type));
 +        wide_int shift = r2val;
 +        if (shift == 0)
 +          {
 +            *mask = r1mask;
 +            *val = r1val;
 +          }
 +        else 
 +          {
 +            if (wi::neg_p (shift))
 +              {
 +                shift = -shift;
 +                if (code == RROTATE_EXPR)
 +                  code = LROTATE_EXPR;
 +                else
 +                  code = RROTATE_EXPR;
 +              }
 +            if (code == RROTATE_EXPR)
 +              {
 +                *mask = wi::rrotate (r1mask, shift, width);
 +                *val = wi::rrotate (r1val, shift, width);
 +              }
 +            else
 +              {
 +                *mask = wi::lrotate (r1mask, shift, width);
 +                *val = wi::lrotate (r1val, shift, width);
 +              }
 +          }
        }
        break;
  
        /* ???  We can handle partially known shift counts if we know
         its sign.  That way we can tell that (x << (y | 8)) & 255
         is zero.  */
 -      if (r2mask.is_zero ())
 +      if (r2mask == 0)
        {
 -        HOST_WIDE_INT shift = r2val.low;
 -        if (code == RSHIFT_EXPR)
 -          shift = -shift;
 -        /* We need to know if we are doing a left or a right shift
 -           to properly shift in zeros for left shift and unsigned
 -           right shifts and the sign bit for signed right shifts.
 -           For signed right shifts we shift in varying in case
 -           the sign bit was varying.  */
 -        if (shift > 0)
 -          {
 -            *mask = r1mask.llshift (shift, TYPE_PRECISION (type));
 -            *val = r1val.llshift (shift, TYPE_PRECISION (type));
 -          }
 -        else if (shift < 0)
 -          {
 -            shift = -shift;
 -            *mask = r1mask.rshift (shift, TYPE_PRECISION (type), !uns);
 -            *val = r1val.rshift (shift, TYPE_PRECISION (type), !uns);
 -          }
 -        else
 +        wide_int shift = r2val;
 +        if (shift == 0)
            {
              *mask = r1mask;
              *val = r1val;
            }
 +        else 
 +          {
 +            if (wi::neg_p (shift))
 +              {
 +                shift = -shift;
 +                if (code == RSHIFT_EXPR)
 +                  code = LSHIFT_EXPR;
 +                else
 +                  code = RSHIFT_EXPR;
 +              }
 +            int shift_precision = SHIFT_COUNT_TRUNCATED ? width : 0;
 +            if (code == RSHIFT_EXPR)
 +              {
 +                *mask = wi::rshift (wi::ext (r1mask, width, sgn),
 +                                    shift, sgn, shift_precision);
 +                *val = wi::rshift (wi::ext (r1val, width, sgn),
 +                                   shift, sgn, shift_precision);
 +              }
 +            else
 +              {
 +                *mask = wi::ext (wi::lshift (r1mask, shift, shift_precision),
 +                                 width, sgn);
 +                *val = wi::ext (wi::lshift (r1val, shift, shift_precision),
 +                                width, sgn);
 +              }
 +          }
        }
        break;
  
      case PLUS_EXPR:
      case POINTER_PLUS_EXPR:
        {
 -      double_int lo, hi;
        /* Do the addition with unknown bits set to zero, to give carry-ins of
           zero wherever possible.  */
 -      lo = r1val.and_not (r1mask) + r2val.and_not (r2mask);
 -      lo = lo.ext (TYPE_PRECISION (type), uns);
 +      widest_int lo = r1val.and_not (r1mask) + r2val.and_not (r2mask);
 +      lo = wi::ext (lo, width, sgn);
        /* Do the addition with unknown bits set to one, to give carry-ins of
           one wherever possible.  */
 -      hi = (r1val | r1mask) + (r2val | r2mask);
 -      hi = hi.ext (TYPE_PRECISION (type), uns);
 +      widest_int hi = (r1val | r1mask) + (r2val | r2mask);
 +      hi = wi::ext (hi, width, sgn);
        /* Each bit in the result is known if (a) the corresponding bits in
           both inputs are known, and (b) the carry-in to that bit position
           is known.  We can check condition (b) by seeing if we got the same
           result with minimised carries as with maximised carries.  */
        *mask = r1mask | r2mask | (lo ^ hi);
 -      *mask = (*mask).ext (TYPE_PRECISION (type), uns);
 +      *mask = wi::ext (*mask, width, sgn);
        /* It shouldn't matter whether we choose lo or hi here.  */
        *val = lo;
        break;
  
      case MINUS_EXPR:
        {
 -      double_int temv, temm;
 +      widest_int temv, temm;
        bit_value_unop_1 (NEGATE_EXPR, r2type, &temv, &temm,
                          r2type, r2val, r2mask);
        bit_value_binop_1 (PLUS_EXPR, type, val, mask,
        {
        /* Just track trailing zeros in both operands and transfer
           them to the other.  */
 -      int r1tz = (r1val | r1mask).trailing_zeros ();
 -      int r2tz = (r2val | r2mask).trailing_zeros ();
 -      if (r1tz + r2tz >= HOST_BITS_PER_DOUBLE_INT)
 +      int r1tz = wi::ctz (r1val | r1mask);
 +      int r2tz = wi::ctz (r2val | r2mask);
 +      if (r1tz + r2tz >= width)
          {
 -          *mask = double_int_zero;
 -          *val = double_int_zero;
 +          *mask = 0;
 +          *val = 0;
          }
        else if (r1tz + r2tz > 0)
          {
 -          *mask = ~double_int::mask (r1tz + r2tz);
 -          *mask = (*mask).ext (TYPE_PRECISION (type), uns);
 -          *val = double_int_zero;
 +          *mask = wi::ext (wi::mask <widest_int> (r1tz + r2tz, true),
 +                           width, sgn);
 +          *val = 0;
          }
        break;
        }
      case EQ_EXPR:
      case NE_EXPR:
        {
 -      double_int m = r1mask | r2mask;
 +      widest_int m = r1mask | r2mask;
        if (r1val.and_not (m) != r2val.and_not (m))
          {
 -          *mask = double_int_zero;
 -          *val = ((code == EQ_EXPR) ? double_int_zero : double_int_one);
 +          *mask = 0;
 +          *val = ((code == EQ_EXPR) ? 0 : 1);
          }
        else
          {
            /* We know the result of a comparison is always one or zero.  */
 -          *mask = double_int_one;
 -          *val = double_int_zero;
 +          *mask = 1;
 +          *val = 0;
          }
        break;
        }
  
      case GE_EXPR:
      case GT_EXPR:
 -      {
 -      double_int tem = r1val;
 -      r1val = r2val;
 -      r2val = tem;
 -      tem = r1mask;
 -      r1mask = r2mask;
 -      r2mask = tem;
 -      code = swap_tree_comparison (code);
 -      }
 -      /* Fallthru.  */
      case LT_EXPR:
      case LE_EXPR:
        {
 +      widest_int o1val, o2val, o1mask, o2mask;
        int minmax, maxmin;
 +
 +      if ((code == GE_EXPR) || (code == GT_EXPR)) 
 +        {
 +          o1val = r2val;
 +          o1mask = r2mask;
 +          o2val = r1val;
 +          o2mask = r1mask;
 +          code = swap_tree_comparison (code);
 +        } 
 +      else
 +        {
 +          o1val = r1val;
 +          o1mask = r1mask;
 +          o2val = r2val;
 +          o2mask = r2mask;
 +        }
        /* If the most significant bits are not known we know nothing.  */
 -      if (r1mask.is_negative () || r2mask.is_negative ())
 +      if (wi::neg_p (o1mask) || wi::neg_p (o2mask))
          break;
  
        /* For comparisons the signedness is in the comparison operands.  */
 -      uns = TYPE_UNSIGNED (r1type);
 +      sgn = TYPE_SIGN (r1type);
  
        /* If we know the most significant bits we know the values
           value ranges by means of treating varying bits as zero
           or one.  Do a cross comparison of the max/min pairs.  */
 -      maxmin = (r1val | r1mask).cmp (r2val.and_not (r2mask), uns);
 -      minmax = r1val.and_not (r1mask).cmp (r2val | r2mask, uns);
 -      if (maxmin < 0)  /* r1 is less than r2.  */
 +      maxmin = wi::cmp (o1val | o1mask, o2val.and_not (o2mask), sgn);
 +      minmax = wi::cmp (o1val.and_not (o1mask), o2val | o2mask, sgn);
 +      if (maxmin < 0)  /* o1 is less than o2.  */
          {
 -          *mask = double_int_zero;
 -          *val = double_int_one;
 +          *mask = 0;
 +          *val = 1;
          }
 -      else if (minmax > 0)  /* r1 is not less or equal to r2.  */
 +      else if (minmax > 0)  /* o1 is not less or equal to o2.  */
          {
 -          *mask = double_int_zero;
 -          *val = double_int_zero;
 +          *mask = 0;
 +          *val = 0;
          }
 -      else if (maxmin == minmax)  /* r1 and r2 are equal.  */
 +      else if (maxmin == minmax)  /* o1 and o2 are equal.  */
          {
            /* This probably should never happen as we'd have
               folded the thing during fully constant value folding.  */
 -          *mask = double_int_zero;
 -          *val = (code == LE_EXPR ? double_int_one :  double_int_zero);
 +          *mask = 0;
 +          *val = (code == LE_EXPR ? 1 : 0);
          }
        else
          {
            /* We know the result of a comparison is always one or zero.  */
 -          *mask = double_int_one;
 -          *val = double_int_zero;
 +          *mask = 1;
 +          *val = 0;
          }
        break;
        }
@@@ -1400,7 -1387,7 +1434,7 @@@ static prop_value_
  bit_value_unop (enum tree_code code, tree type, tree rhs)
  {
    prop_value_t rval = get_value_for_expr (rhs, true);
 -  double_int value, mask;
 +  widest_int value, mask;
    prop_value_t val;
  
    if (rval.lattice_val == UNDEFINED)
  
    gcc_assert ((rval.lattice_val == CONSTANT
               && TREE_CODE (rval.value) == INTEGER_CST)
 -            || rval.mask.is_minus_one ());
 +            || rval.mask == -1);
    bit_value_unop_1 (code, type, &value, &mask,
 -                  TREE_TYPE (rhs), value_to_double_int (rval), rval.mask);
 -  if (!mask.is_minus_one ())
 +                  TREE_TYPE (rhs), value_to_wide_int (rval), rval.mask);
 +  if (mask != -1)
      {
        val.lattice_val = CONSTANT;
        val.mask = mask;
        /* ???  Delay building trees here.  */
 -      val.value = double_int_to_tree (type, value);
 +      val.value = wide_int_to_tree (type, value);
      }
    else
      {
        val.lattice_val = VARYING;
        val.value = NULL_TREE;
 -      val.mask = double_int_minus_one;
 +      val.mask = -1;
      }
    return val;
  }
@@@ -1435,7 -1422,7 +1469,7 @@@ bit_value_binop (enum tree_code code, t
  {
    prop_value_t r1val = get_value_for_expr (rhs1, true);
    prop_value_t r2val = get_value_for_expr (rhs2, true);
 -  double_int value, mask;
 +  widest_int value, mask;
    prop_value_t val;
  
    if (r1val.lattice_val == UNDEFINED
      {
        val.lattice_val = VARYING;
        val.value = NULL_TREE;
 -      val.mask = double_int_minus_one;
 +      val.mask = -1;
        return val;
      }
  
    gcc_assert ((r1val.lattice_val == CONSTANT
               && TREE_CODE (r1val.value) == INTEGER_CST)
 -            || r1val.mask.is_minus_one ());
 +            || r1val.mask == -1);
    gcc_assert ((r2val.lattice_val == CONSTANT
               && TREE_CODE (r2val.value) == INTEGER_CST)
 -            || r2val.mask.is_minus_one ());
 +            || r2val.mask == -1);
    bit_value_binop_1 (code, type, &value, &mask,
 -                   TREE_TYPE (rhs1), value_to_double_int (r1val), r1val.mask,
 -                   TREE_TYPE (rhs2), value_to_double_int (r2val), r2val.mask);
 -  if (!mask.is_minus_one ())
 +                   TREE_TYPE (rhs1), value_to_wide_int (r1val), r1val.mask,
 +                   TREE_TYPE (rhs2), value_to_wide_int (r2val), r2val.mask);
 +  if (mask != -1)
      {
        val.lattice_val = CONSTANT;
        val.mask = mask;
        /* ???  Delay building trees here.  */
 -      val.value = double_int_to_tree (type, value);
 +      val.value = wide_int_to_tree (type, value);
      }
    else
      {
        val.lattice_val = VARYING;
        val.value = NULL_TREE;
 -      val.mask = double_int_minus_one;
 +      val.mask = -1;
      }
    return val;
  }
@@@ -1483,50 -1470,49 +1517,50 @@@ bit_value_assume_aligned (gimple stmt
    unsigned HOST_WIDE_INT aligni, misaligni = 0;
    prop_value_t ptrval = get_value_for_expr (ptr, true);
    prop_value_t alignval;
 -  double_int value, mask;
 +  widest_int value, mask;
    prop_value_t val;
 +
    if (ptrval.lattice_val == UNDEFINED)
      return ptrval;
    gcc_assert ((ptrval.lattice_val == CONSTANT
               && TREE_CODE (ptrval.value) == INTEGER_CST)
 -            || ptrval.mask.is_minus_one ());
 +            || ptrval.mask == -1);
    align = gimple_call_arg (stmt, 1);
 -  if (!host_integerp (align, 1))
 +  if (!tree_fits_uhwi_p (align))
      return ptrval;
 -  aligni = tree_low_cst (align, 1);
 +  aligni = tree_to_uhwi (align);
    if (aligni <= 1
        || (aligni & (aligni - 1)) != 0)
      return ptrval;
    if (gimple_call_num_args (stmt) > 2)
      {
        misalign = gimple_call_arg (stmt, 2);
 -      if (!host_integerp (misalign, 1))
 +      if (!tree_fits_uhwi_p (misalign))
        return ptrval;
 -      misaligni = tree_low_cst (misalign, 1);
 +      misaligni = tree_to_uhwi (misalign);
        if (misaligni >= aligni)
        return ptrval;
      }
    align = build_int_cst_type (type, -aligni);
    alignval = get_value_for_expr (align, true);
    bit_value_binop_1 (BIT_AND_EXPR, type, &value, &mask,
 -                   type, value_to_double_int (ptrval), ptrval.mask,
 -                   type, value_to_double_int (alignval), alignval.mask);
 -  if (!mask.is_minus_one ())
 +                   type, value_to_wide_int (ptrval), ptrval.mask,
 +                   type, value_to_wide_int (alignval), alignval.mask);
 +  if (mask != -1)
      {
        val.lattice_val = CONSTANT;
        val.mask = mask;
 -      gcc_assert ((mask.low & (aligni - 1)) == 0);
 -      gcc_assert ((value.low & (aligni - 1)) == 0);
 -      value.low |= misaligni;
 +      gcc_assert ((mask.to_uhwi () & (aligni - 1)) == 0);
 +      gcc_assert ((value.to_uhwi () & (aligni - 1)) == 0);
 +      value |= misaligni;
        /* ???  Delay building trees here.  */
 -      val.value = double_int_to_tree (type, value);
 +      val.value = wide_int_to_tree (type, value);
      }
    else
      {
        val.lattice_val = VARYING;
        val.value = NULL_TREE;
 -      val.mask = double_int_minus_one;
 +      val.mask = -1;
      }
    return val;
  }
@@@ -1578,7 -1564,7 +1612,7 @@@ evaluate_stmt (gimple stmt
          /* The statement produced a constant value.  */
          val.lattice_val = CONSTANT;
          val.value = simplified;
 -        val.mask = double_int_zero;
 +        val.mask = 0;
        }
      }
    /* If the statement is likely to have a VARYING result, then do not
          /* The statement produced a constant value.  */
          val.lattice_val = CONSTANT;
          val.value = simplified;
 -        val.mask = double_int_zero;
 +        val.mask = 0;
        }
      }
  
        enum gimple_code code = gimple_code (stmt);
        val.lattice_val = VARYING;
        val.value = NULL_TREE;
 -      val.mask = double_int_minus_one;
 +      val.mask = -1;
        if (code == GIMPLE_ASSIGN)
        {
          enum tree_code subcode = gimple_assign_rhs_code (stmt);
            case BUILT_IN_STRNDUP:
              val.lattice_val = CONSTANT;
              val.value = build_int_cst (TREE_TYPE (gimple_get_lhs (stmt)), 0);
 -            val.mask = double_int::from_shwi
 -                         (~(((HOST_WIDE_INT) MALLOC_ABI_ALIGNMENT)
 -                            / BITS_PER_UNIT - 1));
 +            val.mask = ~((HOST_WIDE_INT) MALLOC_ABI_ALIGNMENT
 +                         / BITS_PER_UNIT - 1);
              break;
  
            case BUILT_IN_ALLOCA:
            case BUILT_IN_ALLOCA_WITH_ALIGN:
              align = (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN
 -                     ? TREE_INT_CST_LOW (gimple_call_arg (stmt, 1))
 +                     ? tree_to_hwi (gimple_call_arg (stmt, 1))
                       : BIGGEST_ALIGNMENT);
              val.lattice_val = CONSTANT;
              val.value = build_int_cst (TREE_TYPE (gimple_get_lhs (stmt)), 0);
 -            val.mask = double_int::from_shwi (~(((HOST_WIDE_INT) align)
 -                                                / BITS_PER_UNIT - 1));
 +            val.mask = ~((HOST_WIDE_INT) align / BITS_PER_UNIT - 1);
              break;
  
            /* These builtins return their first argument, unmodified.  */
        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
        if (likelyvalue == UNDEFINED)
        {
          val.lattice_val = likelyvalue;
 -        val.mask = double_int_zero;
 +        val.mask = 0;
        }
        else
        {
          val.lattice_val = VARYING;
 -        val.mask = double_int_minus_one;
 +        val.mask = -1;
        }
  
        val.value = NULL_TREE;
@@@ -1851,10 -1872,10 +1918,10 @@@ fold_builtin_alloca_with_align (gimple 
    arg = get_constant_value (gimple_call_arg (stmt, 0));
    if (arg == NULL_TREE
        || TREE_CODE (arg) != INTEGER_CST
 -      || !host_integerp (arg, 1))
 +      || !tree_fits_uhwi_p (arg))
      return NULL_TREE;
  
 -  size = TREE_INT_CST_LOW (arg);
 +  size = tree_to_hwi (arg);
  
    /* Heuristic: don't fold large allocas.  */
    threshold = (unsigned HOST_WIDE_INT)PARAM_VALUE (PARAM_LARGE_STACK_FRAME);
    n_elem = size * 8 / BITS_PER_UNIT;
    array_type = build_array_type_nelts (elem_type, n_elem);
    var = create_tmp_var (array_type, NULL);
 -  DECL_ALIGN (var) = TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
 +  DECL_ALIGN (var) = tree_to_hwi (gimple_call_arg (stmt, 1));
    {
      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (lhs);
      if (pi != NULL && !pi->pt.anything)
@@@ -1907,7 -1928,7 +1974,7 @@@ ccp_fold_stmt (gimple_stmt_iterator *gs
           fold more conditionals here.  */
        val = evaluate_stmt (stmt);
        if (val.lattice_val != CONSTANT
 -          || !val.mask.is_zero ())
 +          || val.mask != 0)
          return false;
  
        if (dump_file)
@@@ -2087,7 -2108,7 +2154,7 @@@ visit_cond_stmt (gimple stmt, edge *tak
    block = gimple_bb (stmt);
    val = evaluate_stmt (stmt);
    if (val.lattice_val != CONSTANT
 -      || !val.mask.is_zero ())
 +      || val.mask != 0)
      return SSA_PROP_VARYING;
  
    /* Find which edge out of the conditional block will be taken and add it
@@@ -2159,7 -2180,7 +2226,7 @@@ ccp_visit_stmt (gimple stmt, edge *take
       Mark them VARYING.  */
    FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
      {
 -      prop_value_t v = { VARYING, NULL_TREE, { -1, (HOST_WIDE_INT) -1 } };
 +      prop_value_t v = { VARYING, NULL_TREE, -1 };
        set_lattice_value (def, v);
      }
  
diff --combined gcc/tree-ssa-forwprop.c
index 1b5ea19f956ac40986a047b5039a7c9446baf04c,93b89704a2f5d864acc795fc183a04b724e52ed3..5721861331a6a5e9251b87bef787f71cf0ce897b
@@@ -25,11 -25,16 +25,16 @@@ along with GCC; see the file COPYING3
  #include "tm_p.h"
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "tree-pass.h"
  #include "langhooks.h"
  #include "flags.h"
- #include "gimple.h"
  #include "expr.h"
  #include "cfgloop.h"
  #include "optabs.h"
@@@ -812,9 -817,9 +817,9 @@@ forward_propagate_addr_expr_1 (tree nam
        if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0),
                                                         &def_rhs_offset)))
        {
 -        double_int off = mem_ref_offset (lhs);
 +        offset_int off = mem_ref_offset (lhs);
          tree new_ptr;
 -        off += double_int::from_shwi (def_rhs_offset);
 +        off += def_rhs_offset;
          if (TREE_CODE (def_rhs_base) == MEM_REF)
            {
              off += mem_ref_offset (def_rhs_base);
            new_ptr = build_fold_addr_expr (def_rhs_base);
          TREE_OPERAND (lhs, 0) = new_ptr;
          TREE_OPERAND (lhs, 1)
 -          = double_int_to_tree (TREE_TYPE (TREE_OPERAND (lhs, 1)), off);
 +          = wide_int_to_tree (TREE_TYPE (TREE_OPERAND (lhs, 1)), off);
          tidy_after_forward_propagate_addr (use_stmt);
          /* Continue propagating into the RHS if this was not the only use.  */
          if (single_use_p)
        if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0),
                                                         &def_rhs_offset)))
        {
 -        double_int off = mem_ref_offset (rhs);
 +        offset_int off = mem_ref_offset (rhs);
          tree new_ptr;
 -        off += double_int::from_shwi (def_rhs_offset);
 +        off += def_rhs_offset;
          if (TREE_CODE (def_rhs_base) == MEM_REF)
            {
              off += mem_ref_offset (def_rhs_base);
            new_ptr = build_fold_addr_expr (def_rhs_base);
          TREE_OPERAND (rhs, 0) = new_ptr;
          TREE_OPERAND (rhs, 1)
 -          = double_int_to_tree (TREE_TYPE (TREE_OPERAND (rhs, 1)), off);
 +          = wide_int_to_tree (TREE_TYPE (TREE_OPERAND (rhs, 1)), off);
          fold_stmt_inplace (use_stmt_gsi);
          tidy_after_forward_propagate_addr (use_stmt);
          return res;
@@@ -1436,8 -1441,8 +1441,8 @@@ constant_pointer_difference (tree p1, t
                {
                  p = TREE_OPERAND (q, 0);
                  off = size_binop (PLUS_EXPR, off,
 -                                  double_int_to_tree (sizetype,
 -                                                      mem_ref_offset (q)));
 +                                  wide_int_to_tree (sizetype,
 +                                                    mem_ref_offset (q)));
                }
              else
                {
@@@ -1519,8 -1524,8 +1524,8 @@@ simplify_builtin_call (gimple_stmt_iter
          char *src_buf;
          use_operand_p use_p;
  
 -        if (!host_integerp (val2, 0)
 -            || !host_integerp (len2, 1))
 +        if (!tree_fits_shwi_p (val2)
 +            || !tree_fits_uhwi_p (len2))
            break;
          if (is_gimple_call (stmt1))
            {
              src1 = gimple_call_arg (stmt1, 1);
              len1 = gimple_call_arg (stmt1, 2);
              lhs1 = gimple_call_lhs (stmt1);
 -            if (!host_integerp (len1, 1))
 +            if (!tree_fits_uhwi_p (len1))
                break;
              str1 = string_constant (src1, &off1);
              if (str1 == NULL_TREE)
                break;
 -            if (!host_integerp (off1, 1)
 +            if (!tree_fits_uhwi_p (off1)
                  || compare_tree_int (off1, TREE_STRING_LENGTH (str1) - 1) > 0
                  || compare_tree_int (len1, TREE_STRING_LENGTH (str1)
 -                                           - tree_low_cst (off1, 1)) > 0
 +                                           - tree_to_uhwi (off1)) > 0
                  || TREE_CODE (TREE_TYPE (str1)) != ARRAY_TYPE
                  || TYPE_MODE (TREE_TYPE (TREE_TYPE (str1)))
                     != TYPE_MODE (char_type_node))
              src1 = gimple_assign_rhs1 (stmt1);
              if (TREE_CODE (ptr1) != MEM_REF
                  || TYPE_MODE (TREE_TYPE (ptr1)) != TYPE_MODE (char_type_node)
 -                || !host_integerp (src1, 0))
 +                || !tree_fits_shwi_p (src1))
                break;
              ptr1 = build_fold_addr_expr (ptr1);
              callee1 = NULL_TREE;
          /* If the difference between the second and first destination pointer
             is not constant, or is bigger than memcpy length, bail out.  */
          if (diff == NULL
 -            || !host_integerp (diff, 1)
 +            || !tree_fits_uhwi_p (diff)
              || tree_int_cst_lt (len1, diff))
            break;
  
          /* Use maximum of difference plus memset length and memcpy length
             as the new memcpy length, if it is too big, bail out.  */
 -        src_len = tree_low_cst (diff, 1);
 -        src_len += tree_low_cst (len2, 1);
 -        if (src_len < (unsigned HOST_WIDE_INT) tree_low_cst (len1, 1))
 -          src_len = tree_low_cst (len1, 1);
 +        src_len = tree_to_uhwi (diff);
 +        src_len += tree_to_uhwi (len2);
 +        if (src_len < (unsigned HOST_WIDE_INT) tree_to_uhwi (len1))
 +          src_len = tree_to_uhwi (len1);
          if (src_len > 1024)
            break;
  
          src_buf = XALLOCAVEC (char, src_len + 1);
          if (callee1)
            memcpy (src_buf,
 -                  TREE_STRING_POINTER (str1) + tree_low_cst (off1, 1),
 -                  tree_low_cst (len1, 1));
 +                  TREE_STRING_POINTER (str1) + tree_to_uhwi (off1),
 +                  tree_to_uhwi (len1));
          else
 -          src_buf[0] = tree_low_cst (src1, 0);
 -        memset (src_buf + tree_low_cst (diff, 1),
 -                tree_low_cst (val2, 0), tree_low_cst (len2, 1));
 +          src_buf[0] = tree_to_shwi (src1);
 +        memset (src_buf + tree_to_uhwi (diff),
 +                tree_to_shwi (val2), tree_to_uhwi (len2));
          src_buf[src_len] = '\0';
          /* Neither builtin_strncpy_read_str nor builtin_memcpy_read_str
             handle embedded '\0's.  */
@@@ -2309,10 -2314,10 +2314,10 @@@ simplify_rotate (gimple_stmt_iterator *
      return false;
  
    /* CNT1 + CNT2 == B case above.  */
 -  if (host_integerp (def_arg2[0], 1)
 -      && host_integerp (def_arg2[1], 1)
 -      && (unsigned HOST_WIDE_INT) tree_low_cst (def_arg2[0], 1)
 -       + tree_low_cst (def_arg2[1], 1) == TYPE_PRECISION (rtype))
 +  if (tree_fits_uhwi_p (def_arg2[0])
 +      && tree_fits_uhwi_p (def_arg2[1])
 +      && (unsigned HOST_WIDE_INT) tree_to_uhwi (def_arg2[0])
 +       + tree_to_uhwi (def_arg2[1]) == TYPE_PRECISION (rtype))
      rotcnt = def_arg2[0];
    else if (TREE_CODE (def_arg2[0]) != SSA_NAME
           || TREE_CODE (def_arg2[1]) != SSA_NAME)
        /* Check for one shift count being Y and the other B - Y,
           with optional casts.  */
        if (cdef_code[i] == MINUS_EXPR
 -          && host_integerp (cdef_arg1[i], 0)
 -          && tree_low_cst (cdef_arg1[i], 0) == TYPE_PRECISION (rtype)
 +          && tree_fits_shwi_p (cdef_arg1[i])
 +          && tree_to_shwi (cdef_arg1[i]) == TYPE_PRECISION (rtype)
            && TREE_CODE (cdef_arg2[i]) == SSA_NAME)
          {
            tree tem;
           This alternative is safe even for rotation count of 0.
           One shift count is Y and the other (-Y) & (B - 1).  */
        else if (cdef_code[i] == BIT_AND_EXPR
 -               && host_integerp (cdef_arg2[i], 0)
 -               && tree_low_cst (cdef_arg2[i], 0)
 +               && tree_fits_shwi_p (cdef_arg2[i])
 +               && tree_to_shwi (cdef_arg2[i])
                    == TYPE_PRECISION (rtype) - 1
                 && TREE_CODE (cdef_arg1[i]) == SSA_NAME
                 && gimple_assign_rhs_code (stmt) == BIT_IOR_EXPR)
@@@ -2780,7 -2785,7 +2785,7 @@@ associate_pointerplus (gimple_stmt_iter
    if (gimple_assign_rhs1 (def_stmt) != ptr)
      return false;
  
 -  algn = double_int_to_tree (TREE_TYPE (ptr), ~tree_to_double_int (algn));
 +  algn = wide_int_to_tree (TREE_TYPE (ptr), ~wide_int (algn));
    gimple_assign_set_rhs_with_ops (gsi, BIT_AND_EXPR, ptr, algn);
    fold_stmt_inplace (gsi);
    update_stmt (stmt);
@@@ -2942,10 -2947,8 +2947,10 @@@ combine_conversions (gimple_stmt_iterat
          tree tem;
          tem = fold_build2 (BIT_AND_EXPR, inside_type,
                             defop0,
 -                           double_int_to_tree
 -                             (inside_type, double_int::mask (inter_prec)));
 +                           wide_int_to_tree
 +                           (inside_type,
 +                            wi::mask (inter_prec, false,
 +                                      TYPE_PRECISION (inside_type))));
          if (!useless_type_conversion_p (type, inside_type))
            {
              tem = force_gimple_operand_gsi (gsi, tem, true, NULL_TREE, true,
@@@ -3029,11 -3032,11 +3034,11 @@@ simplify_bitfield_ref (gimple_stmt_iter
    if (TREE_TYPE (op) != elem_type)
      return false;
  
 -  size = TREE_INT_CST_LOW (TYPE_SIZE (elem_type));
 -  n = TREE_INT_CST_LOW (op1) / size;
 +  size = tree_to_hwi (TYPE_SIZE (elem_type));
 +  n = tree_to_hwi (op1) / size;
    if (n != 1)
      return false;
 -  idx = TREE_INT_CST_LOW (op2) / size;
 +  idx = tree_to_hwi (op2) / size;
  
    if (code == VEC_PERM_EXPR)
      {
        if (TREE_CODE (m) != VECTOR_CST)
        return false;
        nelts = VECTOR_CST_NELTS (m);
 -      idx = TREE_INT_CST_LOW (VECTOR_CST_ELT (m, idx));
 +      idx = tree_to_hwi (VECTOR_CST_ELT (m, idx));
        idx %= 2 * nelts;
        if (idx < nelts)
        {
@@@ -3087,7 -3090,7 +3092,7 @@@ is_combined_permutation_identity (tree 
      {
        tree val = VECTOR_CST_ELT (mask, i);
        gcc_assert (TREE_CODE (val) == INTEGER_CST);
 -      j = TREE_INT_CST_LOW (val) & (2 * nelts - 1);
 +      j = tree_to_hwi (val) & (2 * nelts - 1);
        if (j == i)
        maybe_identity2 = false;
        else if (j == i + nelts)
@@@ -3232,7 -3235,7 +3237,7 @@@ simplify_vector_constructor (gimple_stm
  
    nelts = TYPE_VECTOR_SUBPARTS (type);
    elem_type = TREE_TYPE (type);
 -  elem_size = TREE_INT_CST_LOW (TYPE_SIZE (elem_type));
 +  elem_size = tree_to_hwi (TYPE_SIZE (elem_type));
  
    sel = XALLOCAVEC (unsigned char, nelts);
    orig = NULL;
            return false;
          orig = ref;
        }
 -      if (TREE_INT_CST_LOW (TREE_OPERAND (op1, 1)) != elem_size)
 +      if (tree_to_hwi (TREE_OPERAND (op1, 1)) != elem_size)
        return false;
 -      sel[i] = TREE_INT_CST_LOW (TREE_OPERAND (op1, 2)) / elem_size;
 +      sel[i] = tree_to_hwi (TREE_OPERAND (op1, 2)) / elem_size;
        if (sel[i] != i) maybe_ident = false;
      }
    if (i < nelts)
diff --combined gcc/tree-ssa-loop-im.c
index bfd2ca7148b4da02c461b753b3dae16141894769,0bcb520ad93fed17c80b15c1c2109b1004899cab..10a86814abd97e5668ddeeb309f4a5e8e7c1ca3b
@@@ -25,7 -25,15 +25,15 @@@ along with GCC; see the file COPYING3
  #include "tm_p.h"
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-into-ssa.h"
  #include "cfgloop.h"
  #include "domwalk.h"
  #include "params.h"
@@@ -1633,7 -1641,7 +1641,7 @@@ mem_refs_may_alias_p (mem_ref_p mem1, m
    /* Perform BASE + OFFSET analysis -- if MEM1 and MEM2 are based on the same
       object and their offset differ in such a way that the locations cannot
       overlap, then they cannot alias.  */
 -  double_int size1, size2;
 +  widest_int size1, size2;
    aff_tree off1, off2;
  
    /* Perform basic offset and type-based disambiguation.  */
    get_inner_reference_aff (mem2->mem.ref, &off2, &size2);
    aff_combination_expand (&off1, ttae_cache);
    aff_combination_expand (&off2, ttae_cache);
 -  aff_combination_scale (&off1, double_int_minus_one);
 +  aff_combination_scale (&off1, -1);
    aff_combination_add (&off2, &off1);
  
    if (aff_comb_cannot_overlap_p (&off2, size1, size2))
index 50ce3a8d2a68c528dd399813df8ae7d4ebd6c786,6f8f04e457ebc10ce334521380559e5ce576b99d..99abd9e480ab3e8c0df46e63413f872ec68ea6e9
@@@ -40,7 -40,17 +40,17 @@@ along with GCC; see the file COPYING3
  #include "tm_p.h"
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-into-ssa.h"
  #include "cfgloop.h"
  #include "tree-pass.h"
  #include "tree-chrec.h"
@@@ -472,7 -482,7 +482,7 @@@ remove_exits_and_undefined_stmts (struc
         into unreachable (or trap when debugging experience is supposed
         to be good).  */
        if (!elt->is_exit
 -        && elt->bound.ult (double_int::from_uhwi (npeeled)))
 +        && wi::ltu_p (elt->bound, npeeled))
        {
          gimple_stmt_iterator gsi = gsi_for_stmt (elt->stmt);
          gimple stmt = gimple_build_call
        }
        /* If we know the exit will be taken after peeling, update.  */
        else if (elt->is_exit
 -             && elt->bound.ule (double_int::from_uhwi (npeeled)))
 +             && wi::leu_p (elt->bound, npeeled))
        {
          basic_block bb = gimple_bb (elt->stmt);
          edge exit_edge = EDGE_SUCC (bb, 0);
@@@ -529,7 -539,7 +539,7 @@@ remove_redundant_iv_tests (struct loop 
        /* Exit is pointless if it won't be taken before loop reaches
         upper bound.  */
        if (elt->is_exit && loop->any_upper_bound
 -          && loop->nb_iterations_upper_bound.ult (elt->bound))
 +          && wi::ltu_p (loop->nb_iterations_upper_bound, elt->bound))
        {
          basic_block bb = gimple_bb (elt->stmt);
          edge exit_edge = EDGE_SUCC (bb, 0);
              || !integer_zerop (niter.may_be_zero)
              || !niter.niter
              || TREE_CODE (niter.niter) != INTEGER_CST
 -            || !loop->nb_iterations_upper_bound.ult
 -                 (tree_to_double_int (niter.niter)))
 +            || !wi::ltu_p (loop->nb_iterations_upper_bound,
 +                           wi::to_widest (niter.niter)))
            continue;
          
          if (dump_file && (dump_flags & TDF_DETAILS))
@@@ -656,9 -666,9 +666,9 @@@ try_unroll_loop_completely (struct loo
       If the number of execution of loop is determined by standard induction
       variable test, then EXIT and EDGE_TO_CANCEL are the two edges leaving
       from the iv test.  */
 -  if (host_integerp (niter, 1))
 +  if (tree_fits_uhwi_p (niter))
      {
 -      n_unroll = tree_low_cst (niter, 1);
 +      n_unroll = tree_to_uhwi (niter);
        n_unroll_found = true;
        edge_to_cancel = EDGE_SUCC (exit->src, 0);
        if (edge_to_cancel == exit)
@@@ -928,7 -938,7 +938,7 @@@ canonicalize_loop_induction_variables (
       by find_loop_niter_by_eval.  Be sure to keep it for future.  */
    if (niter && TREE_CODE (niter) == INTEGER_CST)
      {
 -      record_niter_bound (loop, tree_to_double_int (niter),
 +      record_niter_bound (loop, wi::to_widest (niter),
                          exit == single_likely_exit (loop), true);
      }
  
@@@ -1090,7 -1100,7 +1100,7 @@@ propagate_constants_for_unrolling (basi
  
  static bool
  tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer,
-                               vec<loop_p, va_stack>& father_stack,
+                               vec<loop_p, va_heap>& father_stack,
                                struct loop *loop)
  {
    struct loop *loop_father;
  unsigned int
  tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
  {
-   vec<loop_p, va_stack> father_stack;
+   stack_vec<loop_p, 16> father_stack;
    bool changed;
    int iteration = 0;
    bool irred_invalidated = false;
  
-   vec_stack_alloc (loop_p, father_stack, 16);
    do
      {
        changed = false;
index 6846fcf6115b6f8bf26a1a2308bfb6258c430875,0210dbbad3df77299bc5ad12522c798038243ad6..9e6a9920bad4968e694d7c6e4346d52ccd4174a7
@@@ -69,6 -69,18 +69,18 @@@ along with GCC; see the file COPYING3
  #include "tm_p.h"
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-ivopts.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "cfgloop.h"
  #include "tree-pass.h"
@@@ -1563,19 -1575,19 +1575,19 @@@ idx_record_use (tree base, tree *idx
     signedness of TOP and BOT.  */
  
  static bool
 -constant_multiple_of (tree top, tree bot, double_int *mul)
 +constant_multiple_of (tree top, tree bot, widest_int *mul)
  {
    tree mby;
    enum tree_code code;
 -  double_int res, p0, p1;
    unsigned precision = TYPE_PRECISION (TREE_TYPE (top));
 +  widest_int res, p0, p1;
  
    STRIP_NOPS (top);
    STRIP_NOPS (bot);
  
    if (operand_equal_p (top, bot, 0))
      {
 -      *mul = double_int_one;
 +      *mul = 1;
        return true;
      }
  
        if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &res))
        return false;
  
 -      *mul = (res * tree_to_double_int (mby)).sext (precision);
 +      *mul = wi::sext (res * wi::to_widest (mby), precision);
        return true;
  
      case PLUS_EXPR:
  
        if (code == MINUS_EXPR)
        p1 = -p1;
 -      *mul = (p0 + p1).sext (precision);
 +      *mul = wi::sext (p0 + p1, precision);
        return true;
  
      case INTEGER_CST:
        if (TREE_CODE (bot) != INTEGER_CST)
        return false;
  
 -      p0 = tree_to_double_int (top).sext (precision);
 -      p1 = tree_to_double_int (bot).sext (precision);
 -      if (p1.is_zero ())
 +      p0 = widest_int::from (top, SIGNED);
 +      p1 = widest_int::from (bot, SIGNED);
 +      if (p1 == 0)
        return false;
 -      *mul = p0.sdivmod (p1, FLOOR_DIV_EXPR, &res).sext (precision);
 -      return res.is_zero ();
 +      *mul = wi::sext (wi::divmod_trunc (p0, p1, SIGNED, &res), precision);
 +      return res == 0;
  
      default:
        return false;
@@@ -2011,12 -2023,12 +2023,12 @@@ find_interesting_uses (struct ivopts_da
  
  static tree
  strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
-               unsigned HOST_WIDE_INT *offset)
+               HOST_WIDE_INT *offset)
  {
    tree op0 = NULL_TREE, op1 = NULL_TREE, tmp, step;
    enum tree_code code;
    tree type, orig_type = TREE_TYPE (expr);
-   unsigned HOST_WIDE_INT off0, off1, st;
+   HOST_WIDE_INT off0, off1, st;
    tree orig_expr = expr;
  
    STRIP_NOPS (expr);
    switch (code)
      {
      case INTEGER_CST:
 -      if (!cst_and_fits_in_hwi (expr)
 +      if (!cst_fits_shwi_p (expr)
          || integer_zerop (expr))
        return orig_expr;
  
  
      case MULT_EXPR:
        op1 = TREE_OPERAND (expr, 1);
 -      if (!cst_and_fits_in_hwi (op1))
 +      if (!cst_fits_shwi_p (op1))
        return orig_expr;
  
        op0 = TREE_OPERAND (expr, 0);
        return orig_expr;
  
        step = array_ref_element_size (expr);
 -      if (!cst_and_fits_in_hwi (step))
 +      if (!cst_fits_shwi_p (step))
        break;
  
        st = int_cst_value (step);
        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:
  static tree
  strip_offset (tree expr, unsigned HOST_WIDE_INT *offset)
  {
-   return strip_offset_1 (expr, false, false, offset);
+   HOST_WIDE_INT off;
+   tree core = strip_offset_1 (expr, false, false, &off);
+   *offset = off;
+   return core;
  }
  
  /* Returns variant of TYPE that can be used as base for different uses.
@@@ -2364,7 -2392,7 +2392,7 @@@ add_autoinc_candidates (struct ivopts_d
    if (use_bb->loop_father != data->current_loop
        || !dominated_by_p (CDI_DOMINATORS, data->current_loop->latch, use_bb)
        || stmt_could_throw_p (use->stmt)
 -      || !cst_and_fits_in_hwi (step))
 +      || !cst_fits_shwi_p (step))
      return;
  
    cstepi = int_cst_value (step);
@@@ -2627,9 -2655,6 +2655,9 @@@ new_cost (unsigned runtime, unsigned co
  {
    comp_cost cost;
  
 +  static int ct = 0;
 +  ct++;
 +
    cost.cost = runtime;
    cost.complexity = complexity;
  
@@@ -2969,7 -2994,7 +2997,7 @@@ get_computation_aff (struct loop *loop
    tree common_type, var;
    tree uutype;
    aff_tree cbase_aff, var_aff;
 -  double_int rat;
 +  widest_int rat;
  
    if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype))
      {
@@@ -3111,16 -3136,19 +3139,19 @@@ multiplier_allowed_in_address_p (HOST_W
      {
        enum machine_mode address_mode = targetm.addr_space.address_mode (as);
        rtx reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
-       rtx addr;
+       rtx reg2 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2);
+       rtx addr, scaled;
        HOST_WIDE_INT i;
  
        valid_mult = sbitmap_alloc (2 * MAX_RATIO + 1);
        bitmap_clear (valid_mult);
-       addr = gen_rtx_fmt_ee (MULT, address_mode, reg1, NULL_RTX);
+       scaled = gen_rtx_fmt_ee (MULT, address_mode, reg1, NULL_RTX);
+       addr = gen_rtx_fmt_ee (PLUS, address_mode, scaled, reg2);
        for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
        {
-         XEXP (addr, 1) = gen_int_mode (i, address_mode);
-         if (memory_address_addr_space_p (mode, addr, as))
+         XEXP (scaled, 1) = gen_int_mode (i, address_mode);
+         if (memory_address_addr_space_p (mode, addr, as)
+             || memory_address_addr_space_p (mode, scaled, as))
            bitmap_set_bit (valid_mult, i + MAX_RATIO);
        }
  
@@@ -3470,7 -3498,6 +3501,7 @@@ get_shiftadd_cost (tree expr, enum mach
      res = add_costs (res, force_expr_to_var_cost (multop, speed));
  
    *cost = res;
 +
    return true;
  }
  
@@@ -3585,7 -3612,6 +3616,7 @@@ force_expr_to_var_cost (tree expr, boo
        break;
  
      default:
 +
        /* Just an arbitrary value, FIXME.  */
        return new_cost (target_spill_cost[speed], 0);
      }
              mult = op0;
  
            if (mult != NULL_TREE
 -              && cst_and_fits_in_hwi (TREE_OPERAND (mult, 1))
 +              && cst_fits_shwi_p (TREE_OPERAND (mult, 1))
                && get_shiftadd_cost (expr, mode, cost0, cost1, mult,
                                      speed, &sa_cost))
              return sa_cost;
        break;
  
      case MULT_EXPR:
 -      if (cst_and_fits_in_hwi (op0))
 +      if (cst_fits_shwi_p (op0))
        cost = new_cost (mult_by_coeff_cost (int_cst_value (op0),
                                             mode, speed), 0);
 -      else if (cst_and_fits_in_hwi (op1))
 +      else if (cst_fits_shwi_p (op1))
        cost = new_cost (mult_by_coeff_cost (int_cst_value (op1),
                                             mode, speed), 0);
        else
@@@ -3739,7 -3765,7 +3770,7 @@@ ptr_difference_cost (struct ivopts_dat
    type = signed_type_for (TREE_TYPE (e1));
    tree_to_aff_combination (e1, type, &aff_e1);
    tree_to_aff_combination (e2, type, &aff_e2);
 -  aff_combination_scale (&aff_e2, double_int_minus_one);
 +  aff_combination_scale (&aff_e2, -1);
    aff_combination_add (&aff_e1, &aff_e2);
  
    return force_var_cost (data, aff_combination_to_tree (&aff_e1), depends_on);
@@@ -3794,7 -3820,7 +3825,7 @@@ difference_cost (struct ivopts_data *da
    type = signed_type_for (TREE_TYPE (e1));
    tree_to_aff_combination (e1, type, &aff_e1);
    tree_to_aff_combination (e2, type, &aff_e2);
 -  aff_combination_scale (&aff_e2, double_int_minus_one);
 +  aff_combination_scale (&aff_e2, -1);
    aff_combination_add (&aff_e1, &aff_e2);
  
    return force_var_cost (data, aff_combination_to_tree (&aff_e1), depends_on);
@@@ -3913,16 -3939,16 +3944,16 @@@ get_loop_invariant_expr_id (struct ivop
              {
                tree ind = TREE_OPERAND (usym, 1);
                if (TREE_CODE (ind) == INTEGER_CST
 -                  && host_integerp (ind, 0)
 -                  && TREE_INT_CST_LOW (ind) == 0)
 +                  && tree_fits_shwi_p (ind)
 +                  && tree_to_shwi (ind) == 0)
                  usym = TREE_OPERAND (usym, 0);
              }
            if (TREE_CODE (csym) == ARRAY_REF)
              {
                tree ind = TREE_OPERAND (csym, 1);
                if (TREE_CODE (ind) == INTEGER_CST
 -                  && host_integerp (ind, 0)
 -                  && TREE_INT_CST_LOW (ind) == 0)
 +                  && tree_fits_shwi_p (ind)
 +                  && tree_to_shwi (ind) == 0)
                  csym = TREE_OPERAND (csym, 0);
              }
            if (operand_equal_p (usym, csym, 0))
    tree_to_aff_combination (ub, TREE_TYPE (ub), &ubase_aff);
    tree_to_aff_combination (cb, TREE_TYPE (cb), &cbase_aff);
  
 -  aff_combination_scale (&cbase_aff, double_int::from_shwi (-1 * ratio));
 +  aff_combination_scale (&cbase_aff, -1 * ratio);
    aff_combination_add (&ubase_aff, &cbase_aff);
    expr = aff_combination_to_tree (&ubase_aff);
    return get_expr_id (data, expr);
@@@ -3968,7 -3994,7 +3999,7 @@@ get_computation_cost_at (struct ivopts_
    HOST_WIDE_INT ratio, aratio;
    bool var_present, symbol_present, stmt_is_after_inc;
    comp_cost cost;
 -  double_int rat;
 +  widest_int rat;
    bool speed = optimize_bb_for_speed_p (gimple_bb (at));
    enum machine_mode mem_mode = (address_p
                                ? TYPE_MODE (TREE_TYPE (*use->op_p))
       redundancy elimination is likely to transform the code so that
       it uses value of the variable before increment anyway,
       so it is not that much unrealistic.  */
 -  if (cst_and_fits_in_hwi (cstep))
 +  if (cst_fits_shwi_p (cstep))
      cstepi = int_cst_value (cstep);
    else
      cstepi = 0;
    if (!constant_multiple_of (ustep, cstep, &rat))
      return infinite_cost;
  
 -  if (rat.fits_shwi ())
 +  if (wi::fits_shwi_p (rat))
      ratio = rat.to_shwi ();
    else
      return infinite_cost;
  
       (also holds in the case ratio == -1, TODO.  */
  
 -  if (cst_and_fits_in_hwi (cbase))
 +  if (cst_fits_shwi_p (cbase))
      {
        offset = - ratio * int_cst_value (cbase);
        cost = difference_cost (data,
@@@ -4299,7 -4325,7 +4330,7 @@@ iv_period (struct iv *iv
  
    period = build_low_bits_mask (type,
                                  (TYPE_PRECISION (type)
 -                                 - tree_low_cst (pow2div, 1)));
 +                                 - tree_to_uhwi (pow2div)));
  
    return period;
  }
@@@ -4497,7 -4523,7 +4528,7 @@@ iv_elimination_compare_lt (struct ivopt
  
    /* We need to be able to decide whether candidate is increasing or decreasing
       in order to choose the right comparison operator.  */
 -  if (!cst_and_fits_in_hwi (cand->iv->step))
 +  if (!cst_fits_shwi_p (cand->iv->step))
      return false;
    step = int_cst_value (cand->iv->step);
  
    tree_to_aff_combination (niter->niter, nit_type, &nit);
    tree_to_aff_combination (fold_convert (nit_type, a), nit_type, &tmpa);
    tree_to_aff_combination (fold_convert (nit_type, b), nit_type, &tmpb);
 -  aff_combination_scale (&nit, double_int_minus_one);
 -  aff_combination_scale (&tmpa, double_int_minus_one);
 +  aff_combination_scale (&nit, -1);
 +  aff_combination_scale (&tmpa, -1);
    aff_combination_add (&tmpb, &tmpa);
    aff_combination_add (&tmpb, &nit);
 -  if (tmpb.n != 0 || tmpb.offset != double_int_one)
 +  if (tmpb.n != 0 || tmpb.offset != 1)
      return false;
  
    /* Finally, check that CAND->IV->BASE - CAND->IV->STEP * A does not
@@@ -4627,13 -4653,13 +4658,13 @@@ may_eliminate_iv (struct ivopts_data *d
       entire loop and compare against that instead.  */
    else
      {
 -      double_int period_value, max_niter;
 +      widest_int period_value, max_niter;
  
        max_niter = desc->max;
        if (stmt_after_increment (loop, cand, use->stmt))
 -        max_niter += double_int_one;
 -      period_value = tree_to_double_int (period);
 -      if (max_niter.ugt (period_value))
 +        max_niter += 1;
 +      period_value = wi::to_widest (period);
 +      if (wi::gtu_p (max_niter, period_value))
          {
            /* See if we can take advantage of inferred loop bound information.  */
            if (data->loop_single_exit_p)
                if (!max_loop_iterations (loop, &max_niter))
                  return false;
                /* The loop bound is already adjusted by adding 1.  */
 -              if (max_niter.ugt (period_value))
 +              if (wi::gtu_p (max_niter, period_value))
                  return false;
              }
            else
index 0b37c91f68dbd120eaaa7606036f9b5eaa1f6aee,c3e0ef26af7c1adbcd9573ce171dc33b14d960d0..9a07db20e61eb4c2e7bce1abc06f6f1d7a3046af
@@@ -26,7 -26,14 +26,14 @@@ along with GCC; see the file COPYING3
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
  #include "intl.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssa-loop-ivopts.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
  #include "dumpfile.h"
  #include "cfgloop.h"
  #include "ggc.h"
@@@ -38,7 -45,6 +45,7 @@@
  #include "diagnostic-core.h"
  #include "tree-inline.h"
  #include "tree-pass.h"
 +#include "wide-int-print.h"
  
  
  #define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
@@@ -69,6 -75,7 +76,6 @@@ split_to_var_and_offset (tree expr, tre
  {
    tree type = TREE_TYPE (expr);
    tree op0, op1;
 -  double_int off;
    bool negate = false;
  
    *var = expr;
  
        *var = op0;
        /* Always sign extend the offset.  */
 -      off = tree_to_double_int (op1);
 -      off = off.sext (TYPE_PRECISION (type));
 -      mpz_set_double_int (offset, off, false);
 +      wi::to_mpz (op1, offset, SIGNED);
        if (negate)
        mpz_neg (offset, offset);
        break;
  
      case INTEGER_CST:
        *var = build_int_cst_type (type, 0);
 -      off = tree_to_double_int (expr);
 -      mpz_set_double_int (offset, off, TYPE_UNSIGNED (type));
 +      wi::to_mpz (expr, offset, TYPE_SIGN (type));
        break;
  
      default:
@@@ -167,7 -177,7 +174,7 @@@ bound_difference_of_offsetted_base (tre
      }
  
    mpz_init (m);
 -  mpz_set_double_int (m, double_int::mask (TYPE_PRECISION (type)), true);
 +  wi::to_mpz (wi::minus_one (TYPE_PRECISION (type)), m, UNSIGNED);
    mpz_add_ui (m, m, 1);
    mpz_sub (bnds->up, x, y);
    mpz_set (bnds->below, bnds->up);
@@@ -446,15 -456,15 +453,15 @@@ end
     difference of two values in TYPE.  */
  
  static void
 -bounds_add (bounds *bnds, double_int delta, tree type)
 +bounds_add (bounds *bnds, widest_int delta, tree type)
  {
    mpz_t mdelta, max;
  
    mpz_init (mdelta);
 -  mpz_set_double_int (mdelta, delta, false);
 +  wi::to_mpz (delta, mdelta, SIGNED);
  
    mpz_init (max);
 -  mpz_set_double_int (max, double_int::mask (TYPE_PRECISION (type)), true);
 +  wi::to_mpz (wi::minus_one (TYPE_PRECISION (type)), max, UNSIGNED);
  
    mpz_add (bnds->up, bnds->up, mdelta);
    mpz_add (bnds->below, bnds->below, mdelta);
@@@ -499,8 -509,8 +506,8 @@@ inverse (tree x, tree mask
        unsigned HOST_WIDE_INT imask;
        unsigned HOST_WIDE_INT irslt = 1;
  
 -      gcc_assert (cst_and_fits_in_hwi (x));
 -      gcc_assert (cst_and_fits_in_hwi (mask));
 +      gcc_assert (cst_fits_shwi_p (x));
 +      gcc_assert (cst_fits_shwi_p (mask));
  
        ix = int_cst_value (x);
        imask = int_cst_value (mask);
@@@ -548,7 -558,7 +555,7 @@@ static voi
  number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
                             bounds *bnds, bool exit_must_be_taken)
  {
 -  double_int max;
 +  widest_int max;
    mpz_t d;
    tree type = TREE_TYPE (c);
    bool bnds_u_valid = ((no_overflow && exit_must_be_taken)
    if (integer_onep (s)
        || (TREE_CODE (c) == INTEGER_CST
          && TREE_CODE (s) == INTEGER_CST
 -        && tree_to_double_int (c).mod (tree_to_double_int (s),
 -                                       TYPE_UNSIGNED (type),
 -                                       EXACT_DIV_EXPR).is_zero ())
 -      || (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (c))
 +        && wi::mod_trunc (c, s, TYPE_SIGN (type)) == 0)
 +      || (TYPE_OVERFLOW_UNDEFINED (type)
          && multiple_of_p (type, c, s)))
      {
        /* If C is an exact multiple of S, then its value will be reached before
       the whole # of iterations analysis will fail).  */
    if (!no_overflow)
      {
 -      max = double_int::mask (TYPE_PRECISION (type)
 -                            - tree_low_cst (num_ending_zeros (s), 1));
 -      mpz_set_double_int (bnd, max, true);
 +      max = wi::mask <widest_int> (TYPE_PRECISION (type) - wi::ctz (s), false);
 +      wi::to_mpz (max, bnd, UNSIGNED);
        return;
      }
  
    /* Now we know that the induction variable does not overflow, so the loop
       iterates at most (range of type / S) times.  */
 -  mpz_set_double_int (bnd, double_int::mask (TYPE_PRECISION (type)), true);
 +  wi::to_mpz (wi::minus_one (TYPE_PRECISION (type)), bnd, UNSIGNED);
  
    /* If the induction variable is guaranteed to reach the value of C before
       overflow, ... */
        /* ... then we can strengthen this to C / S, and possibly we can use
         the upper bound on C given by BNDS.  */
        if (TREE_CODE (c) == INTEGER_CST)
 -      mpz_set_double_int (bnd, tree_to_double_int (c), true);
 +      wi::to_mpz (c, bnd, UNSIGNED);
        else if (bnds_u_valid)
        mpz_set (bnd, bnds->up);
      }
  
    mpz_init (d);
 -  mpz_set_double_int (d, tree_to_double_int (s), true);
 +  wi::to_mpz (s, d, UNSIGNED);
    mpz_fdiv_q (bnd, bnd, d);
    mpz_clear (d);
  }
@@@ -649,8 -662,7 +656,8 @@@ number_of_iterations_ne (tree type, aff
    mpz_init (max);
    number_of_iterations_ne_max (max, iv->no_overflow, c, s, bnds,
                               exit_must_be_taken);
 -  niter->max = mpz_get_double_int (niter_type, max, false);
 +  niter->max = widest_int::from (wi::from_mpz (niter_type, max, false),
 +                               TYPE_SIGN (niter_type));
    mpz_clear (max);
  
    /* First the trivial cases -- when the step is 1.  */
    bits = num_ending_zeros (s);
    bound = build_low_bits_mask (niter_type,
                               (TYPE_PRECISION (niter_type)
 -                              - tree_low_cst (bits, 1)));
 +                              - tree_to_uhwi (bits)));
  
    d = fold_binary_to_constant (LSHIFT_EXPR, niter_type,
                               build_int_cst (niter_type, 1), bits);
@@@ -723,7 -735,7 +730,7 @@@ number_of_iterations_lt_to_ne (tree typ
    tmod = fold_convert (type1, mod);
  
    mpz_init (mmod);
 -  mpz_set_double_int (mmod, tree_to_double_int (mod), true);
 +  wi::to_mpz (mod, mmod, UNSIGNED);
    mpz_neg (mmod, mmod);
  
    /* If the induction variable does not overflow and the exit is taken,
      niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
                                      niter->may_be_zero,
                                      noloop);
 -  bounds_add (bnds, tree_to_double_int (mod), type);
 +  bounds_add (bnds, wi::to_widest (mod), type);
    *delta = fold_build2 (PLUS_EXPR, niter_type, *delta, mod);
  
    ret = true;
@@@ -895,7 -907,7 +902,7 @@@ assert_loop_rolls_lt (tree type, affine
    tree assumption = boolean_true_node, bound, diff;
    tree mbz, mbzl, mbzr, type1;
    bool rolls_p, no_overflow_p;
 -  double_int dstep;
 +  widest_int dstep;
    mpz_t mstep, max;
  
    /* We are going to compute the number of iterations as
    /* First check whether the answer does not follow from the bounds we gathered
       before.  */
    if (integer_nonzerop (iv0->step))
 -    dstep = tree_to_double_int (iv0->step);
 +    dstep = wi::to_widest (iv0->step);
    else
      {
 -      dstep = tree_to_double_int (iv1->step).sext (TYPE_PRECISION (type));
 +      dstep = wi::sext (wi::to_widest (iv1->step), TYPE_PRECISION (type));
        dstep = -dstep;
      }
  
    mpz_init (mstep);
 -  mpz_set_double_int (mstep, dstep, true);
 +  wi::to_mpz (dstep, mstep, UNSIGNED);
    mpz_neg (mstep, mstep);
    mpz_add_ui (mstep, mstep, 1);
  
    rolls_p = mpz_cmp (mstep, bnds->below) <= 0;
  
    mpz_init (max);
 -  mpz_set_double_int (max, double_int::mask (TYPE_PRECISION (type)), true);
 +  wi::to_mpz (wi::minus_one (TYPE_PRECISION (type)), max, UNSIGNED);
    mpz_add (max, max, mstep);
    no_overflow_p = (mpz_cmp (bnds->up, max) <= 0
                   /* For pointers, only values lying inside a single object
@@@ -1063,8 -1075,7 +1070,8 @@@ number_of_iterations_lt (tree type, aff
        niter->may_be_zero = fold_build2 (LT_EXPR, boolean_type_node,
                                          iv1->base, iv0->base);
        niter->niter = delta;
 -      niter->max = mpz_get_double_int (niter_type, bnds->up, false);
 +      niter->max = widest_int::from (wi::from_mpz (niter_type, bnds->up, false),
 +                                   TYPE_SIGN (niter_type));
        return true;
      }
  
  
    mpz_init (mstep);
    mpz_init (tmp);
 -  mpz_set_double_int (mstep, tree_to_double_int (step), true);
 +  wi::to_mpz (step, mstep, UNSIGNED);
    mpz_add (tmp, bnds->up, mstep);
    mpz_sub_ui (tmp, tmp, 1);
    mpz_fdiv_q (tmp, tmp, mstep);
 -  niter->max = mpz_get_double_int (niter_type, tmp, false);
 +  niter->max = widest_int::from (wi::from_mpz (niter_type, tmp, false),
 +                               TYPE_SIGN (niter_type));
    mpz_clear (mstep);
    mpz_clear (tmp);
  
@@@ -1175,7 -1185,7 +1182,7 @@@ number_of_iterations_le (tree type, aff
      iv0->base = fold_build2 (MINUS_EXPR, type1,
                             iv0->base, build_int_cst (type1, 1));
  
 -  bounds_add (bnds, double_int_one, type1);
 +  bounds_add (bnds, 1, type1);
  
    return number_of_iterations_lt (type, iv0, iv1, niter, exit_must_be_taken,
                                  bnds);
@@@ -1247,7 -1257,8 +1254,7 @@@ number_of_iterations_cond (struct loop 
    niter->assumptions = boolean_true_node;
    niter->may_be_zero = boolean_false_node;
    niter->niter = NULL_TREE;
 -  niter->max = double_int_zero;
 -
 +  niter->max = 0;
    niter->bound = NULL_TREE;
    niter->cmp = ERROR_MARK;
  
    if (tem && integer_zerop (tem))
      {
        niter->niter = build_int_cst (unsigned_type_for (type), 0);
 -      niter->max = double_int_zero;
 +      niter->max = 0;
        return true;
      }
  
          fprintf (dump_file, "    # of iterations ");
          print_generic_expr (dump_file, niter->niter, TDF_SLIM);
          fprintf (dump_file, ", bounded by ");
 -        dump_double_int (dump_file, niter->max, true);
 +        print_decu (niter->max, dump_file);
          fprintf (dump_file, "\n");
        }
        else
@@@ -1907,7 -1918,7 +1914,7 @@@ number_of_iterations_exit (struct loop 
  
    /* If NITER has simplified into a constant, update MAX.  */
    if (TREE_CODE (niter->niter) == INTEGER_CST)
 -    niter->max = tree_to_double_int (niter->niter);
 +    niter->max = wi::to_widest (niter->niter);
  
    if (integer_onep (niter->assumptions))
      return true;
@@@ -2019,7 -2030,7 +2026,7 @@@ find_loop_niter (struct loop *loop, edg
  bool
  finite_loop_p (struct loop *loop)
  {
 -  double_int nit;
 +  widest_int nit;
    int flags;
  
    if (flag_unsafe_loop_optimizations)
@@@ -2333,13 -2344,13 +2340,13 @@@ find_loop_niter_by_eval (struct loop *l
  
  */
  
 -static double_int derive_constant_upper_bound_ops (tree, tree,
 +static widest_int derive_constant_upper_bound_ops (tree, tree,
                                                   enum tree_code, tree);
  
  /* Returns a constant upper bound on the value of the right-hand side of
     an assignment statement STMT.  */
  
 -static double_int
 +static widest_int
  derive_constant_upper_bound_assign (gimple stmt)
  {
    enum tree_code code = gimple_assign_rhs_code (stmt);
     is considered to be unsigned.  If its type is signed, its value must
     be nonnegative.  */
  
 -static double_int
 +static widest_int
  derive_constant_upper_bound (tree val)
  {
    enum tree_code code;
     whose type is TYPE.  The expression is considered to be unsigned.  If
     its type is signed, its value must be nonnegative.  */
  
 -static double_int
 +static widest_int
  derive_constant_upper_bound_ops (tree type, tree op0,
                                 enum tree_code code, tree op1)
  {
    tree subtype, maxt;
 -  double_int bnd, max, mmax, cst;
 +  widest_int bnd, max, mmax, cst;
    gimple stmt;
  
    if (INTEGRAL_TYPE_P (type))
    else
      maxt = upper_bound_in_type (type, type);
  
 -  max = tree_to_double_int (maxt);
 +  max = wi::to_widest (maxt);
  
    switch (code)
      {
      case INTEGER_CST:
 -      return tree_to_double_int (op0);
 +      return wi::to_widest (op0);
  
      CASE_CONVERT:
        subtype = TREE_TYPE (op0);
  
        /* If the bound does not fit in TYPE, max. value of TYPE could be
         attained.  */
 -      if (max.ult (bnd))
 +      if (wi::ltu_p (max, bnd))
        return max;
  
        return bnd;
        /* Canonicalize to OP0 - CST.  Consider CST to be signed, in order to
         choose the most logical way how to treat this constant regardless
         of the signedness of the type.  */
 -      cst = tree_to_double_int (op1);
 -      cst = cst.sext (TYPE_PRECISION (type));
 +      cst = wi::sext (wi::to_widest (op1), TYPE_PRECISION (type));
        if (code != MINUS_EXPR)
        cst = -cst;
  
        bnd = derive_constant_upper_bound (op0);
  
 -      if (cst.is_negative ())
 +      if (wi::neg_p (cst))
        {
          cst = -cst;
          /* Avoid CST == 0x80000...  */
 -        if (cst.is_negative ())
 +        if (wi::neg_p (cst))
            return max;;
  
          /* OP0 + CST.  We need to check that
             BND <= MAX (type) - CST.  */
  
          mmax -= cst;
 -        if (bnd.ugt (mmax))
 +        if (wi::ltu_p (bnd, max))
            return max;
  
          return bnd + cst;
          /* This should only happen if the type is unsigned; however, for
             buggy programs that use overflowing signed arithmetics even with
             -fno-wrapv, this condition may also be true for signed values.  */
 -        if (bnd.ult (cst))
 +        if (wi::ltu_p (bnd, cst))
            return max;
  
          if (TYPE_UNSIGNED (type))
            {
              tree tem = fold_binary (GE_EXPR, boolean_type_node, op0,
 -                                    double_int_to_tree (type, cst));
 +                                    wide_int_to_tree (type, cst));
              if (!tem || integer_nonzerop (tem))
                return max;
            }
        return max;
  
        bnd = derive_constant_upper_bound (op0);
 -      return bnd.udiv (tree_to_double_int (op1), FLOOR_DIV_EXPR);
 +      return wi::udiv_floor (bnd, wi::to_widest (op1));
  
      case BIT_AND_EXPR:
        if (TREE_CODE (op1) != INTEGER_CST
          || tree_int_cst_sign_bit (op1))
        return max;
 -      return tree_to_double_int (op1);
 +      return wi::to_widest (op1);
  
      case SSA_NAME:
        stmt = SSA_NAME_DEF_STMT (op0);
  
  static void
  do_warn_aggressive_loop_optimizations (struct loop *loop,
 -                                     double_int i_bound, gimple stmt)
 +                                     widest_int i_bound, gimple stmt)
  {
    /* Don't warn if the loop doesn't have known constant bound.  */
    if (!loop->nb_iterations
        || loop->warned_aggressive_loop_optimizations
        /* Only warn if undefined behavior gives us lower estimate than the
         known constant bound.  */
 -      || i_bound.ucmp (tree_to_double_int (loop->nb_iterations)) >= 0
 +      || wi::cmpu (i_bound, wi::to_widest (loop->nb_iterations)) >= 0
        /* And undefined behavior happens unconditionally.  */
        || !dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (stmt)))
      return;
    gimple estmt = last_stmt (e->src);
    if (warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations,
                  "iteration %E invokes undefined behavior",
 -                double_int_to_tree (TREE_TYPE (loop->nb_iterations),
 -                                    i_bound)))
 +                wide_int_to_tree (TREE_TYPE (loop->nb_iterations),
 +                                  i_bound)))
      inform (gimple_location (estmt), "containing loop");
    loop->warned_aggressive_loop_optimizations = true;
  }
     is taken at last when the STMT is executed BOUND + 1 times.
     REALISTIC is true if BOUND is expected to be close to the real number
     of iterations.  UPPER is true if we are sure the loop iterates at most
 -   BOUND times.  I_BOUND is an unsigned double_int upper estimate on BOUND.  */
 +   BOUND times.  I_BOUND is an unsigned wide_int upper estimate on BOUND.  */
  
  static void
 -record_estimate (struct loop *loop, tree bound, double_int i_bound,
 +record_estimate (struct loop *loop, tree bound, widest_int i_bound,
                 gimple at_stmt, bool is_exit, bool realistic, bool upper)
  {
 -  double_int delta;
 +  widest_int delta;
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
               upper ? "" : "probably ");
        print_generic_expr (dump_file, bound, TDF_SLIM);
        fprintf (dump_file, " (bounded by ");
 -      dump_double_int (dump_file, i_bound, true);
 +      print_decu (i_bound, dump_file);
        fprintf (dump_file, ") + 1 times in loop %d.\n", loop->num);
      }
  
    if (TREE_CODE (bound) != INTEGER_CST)
      realistic = false;
    else
 -    gcc_checking_assert (i_bound == tree_to_double_int (bound));
 +    gcc_checking_assert (i_bound == wi::to_widest (bound));
    if (!upper && !realistic)
      return;
  
       otherwise it can be executed BOUND + 1 times.  We will lower the estimate
       later if such statement must be executed on last iteration  */
    if (is_exit)
 -    delta = double_int_zero;
 +    delta = 0;
    else
 -    delta = double_int_one;
 +    delta = 1;
    i_bound += delta;
  
    /* If an overflow occurred, ignore the result.  */
 -  if (i_bound.ult (delta))
 +  if (wi::ltu_p (i_bound, delta))
      return;
  
    if (upper && !is_exit)
@@@ -2625,6 -2637,7 +2632,6 @@@ record_nonwrapping_iv (struct loop *loo
  {
    tree niter_bound, extreme, delta;
    tree type = TREE_TYPE (base), unsigned_type;
 -  double_int max;
  
    if (TREE_CODE (step) != INTEGER_CST || integer_zerop (step))
      return;
    /* STMT is executed at most NITER_BOUND + 1 times, since otherwise the value
       would get out of the range.  */
    niter_bound = fold_build2 (FLOOR_DIV_EXPR, unsigned_type, delta, step);
 -  max = derive_constant_upper_bound (niter_bound);
 +  widest_int max = derive_constant_upper_bound (niter_bound);
    record_estimate (loop, niter_bound, max, stmt, false, realistic, upper);
  }
  
@@@ -2969,21 -2982,27 +2976,21 @@@ infer_loop_bounds_from_undefined (struc
    free (bbs);
  }
  
 -
 -
 -/* Compare double ints, callback for qsort.  */
 +/* Compare wide ints, callback for qsort.  */
  
  static int
 -double_int_cmp (const void *p1, const void *p2)
 +wide_int_cmp (const void *p1, const void *p2)
  {
 -  const double_int *d1 = (const double_int *)p1;
 -  const double_int *d2 = (const double_int *)p2;
 -  if (*d1 == *d2)
 -    return 0;
 -  if (d1->ult (*d2))
 -    return -1;
 -  return 1;
 +  const widest_int *d1 = (const widest_int *) p1;
 +  const widest_int *d2 = (const widest_int *) p2;
 +  return wi::cmpu (*d1, *d2);
  }
  
  /* Return index of BOUND in BOUNDS array sorted in increasing order.
     Lookup by binary search.  */
  
  static int
 -bound_index (vec<double_int> bounds, double_int bound)
 +bound_index (vec<widest_int> bounds, const widest_int &bound)
  {
    unsigned int end = bounds.length ();
    unsigned int begin = 0;
    while (begin != end)
      {
        unsigned int middle = (begin + end) / 2;
 -      double_int index = bounds[middle];
 +      widest_int index = bounds[middle];
  
        if (index == bound)
        return middle;
 -      else if (index.ult (bound))
 +      else if (wi::ltu_p (index, bound))
        begin = middle + 1;
        else
        end = middle;
@@@ -3015,7 -3034,7 +3022,7 @@@ discover_iteration_bound_by_body_walk (
  {
    pointer_map_t *bb_bounds;
    struct nb_iter_bound *elt;
 -  vec<double_int> bounds = vNULL;
 +  vec<widest_int> bounds = vNULL;
    vec<vec<basic_block> > queues = vNULL;
    vec<basic_block> queue = vNULL;
    ptrdiff_t queue_index;
    /* Discover what bounds may interest us.  */
    for (elt = loop->bounds; elt; elt = elt->next)
      {
 -      double_int bound = elt->bound;
 +      widest_int bound = elt->bound;
  
        /* Exit terminates loop at given iteration, while non-exits produce undefined
         effect on the next iteration.  */
        if (!elt->is_exit)
        {
 -        bound += double_int_one;
 +        bound += 1;
          /* If an overflow occurred, ignore the result.  */
 -        if (bound.is_zero ())
 +        if (bound == 0)
            continue;
        }
  
        if (!loop->any_upper_bound
 -        || bound.ult (loop->nb_iterations_upper_bound))
 +        || wi::ltu_p (bound, loop->nb_iterations_upper_bound))
          bounds.safe_push (bound);
      }
  
  
    /* Sort the bounds in decreasing order.  */
    qsort (bounds.address (), bounds.length (),
 -       sizeof (double_int), double_int_cmp);
 +       sizeof (widest_int), wide_int_cmp);
  
    /* For every basic block record the lowest bound that is guaranteed to
       terminate the loop.  */
    bb_bounds = pointer_map_create ();
    for (elt = loop->bounds; elt; elt = elt->next)
      {
 -      double_int bound = elt->bound;
 +      widest_int bound = elt->bound;
        if (!elt->is_exit)
        {
 -        bound += double_int_one;
 +        bound += 1;
          /* If an overflow occurred, ignore the result.  */
 -        if (bound.is_zero ())
 +        if (bound == 0)
            continue;
        }
  
        if (!loop->any_upper_bound
 -        || bound.ult (loop->nb_iterations_upper_bound))
 +        || wi::ltu_p (bound, loop->nb_iterations_upper_bound))
        {
          ptrdiff_t index = bound_index (bounds, bound);
          void **entry = pointer_map_contains (bb_bounds,
        if (dump_file && (dump_flags & TDF_DETAILS))
        {
          fprintf (dump_file, "Found better loop bound ");
 -        dump_double_int (dump_file, bounds[latch_index], true);
 +        print_decu (bounds[latch_index], dump_file);
          fprintf (dump_file, "\n");
        }
        record_niter_bound (loop, bounds[latch_index], false, true);
@@@ -3204,7 -3223,7 +3211,7 @@@ maybe_lower_iteration_bound (struct loo
    for (elt = loop->bounds; elt; elt = elt->next)
      {
        if (!elt->is_exit
 -        && elt->bound.ult (loop->nb_iterations_upper_bound))
 +        && wi::ltu_p (elt->bound, loop->nb_iterations_upper_bound))
        {
          if (!not_executed_last_iteration)
            not_executed_last_iteration = pointer_set_create ();
        if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "Reducing loop iteration estimate by 1; "
                 "undefined statement must be executed at the last iteration.\n");
 -      record_niter_bound (loop, loop->nb_iterations_upper_bound - double_int_one,
 +      record_niter_bound (loop, loop->nb_iterations_upper_bound - 1,
                          false, true);
      }
    BITMAP_FREE (visited);
@@@ -3297,7 -3316,7 +3304,7 @@@ estimate_numbers_of_iterations_loop (st
    unsigned i;
    struct tree_niter_desc niter_desc;
    edge ex;
 -  double_int bound;
 +  widest_int bound;
    edge likely_exit;
  
    /* Give up if we already have tried to compute an estimation.  */
    if (loop->header->count != 0)
      {
        gcov_type nit = expected_loop_iterations_unbounded (loop) + 1;
 -      bound = gcov_type_to_double_int (nit);
 +      bound = gcov_type_to_wide_int (nit);
        record_niter_bound (loop, bound, true, false);
      }
  
        && TREE_CODE (loop->nb_iterations) == INTEGER_CST)
      {
        loop->any_upper_bound = true;
 -      loop->nb_iterations_upper_bound
 -      = tree_to_double_int (loop->nb_iterations);
 +      loop->nb_iterations_upper_bound = wi::to_widest (loop->nb_iterations);
      }
  }
  
     the function returns false, otherwise returns true.  */
  
  bool
 -estimated_loop_iterations (struct loop *loop, double_int *nit)
 +estimated_loop_iterations (struct loop *loop, widest_int *nit)
  {
    /* When SCEV information is available, try to update loop iterations
       estimate.  Otherwise just return whatever we recorded earlier.  */
  HOST_WIDE_INT
  estimated_loop_iterations_int (struct loop *loop)
  {
 -  double_int nit;
 +  widest_int nit;
    HOST_WIDE_INT hwi_nit;
  
    if (!estimated_loop_iterations (loop, &nit))
      return -1;
  
 -  if (!nit.fits_shwi ())
 +  if (!wi::fits_shwi_p (nit))
      return -1;
    hwi_nit = nit.to_shwi ();
  
     false, otherwise returns true.  */
  
  bool
 -max_loop_iterations (struct loop *loop, double_int *nit)
 +max_loop_iterations (struct loop *loop, widest_int *nit)
  {
    /* When SCEV information is available, try to update loop iterations
       estimate.  Otherwise just return whatever we recorded earlier.  */
  HOST_WIDE_INT
  max_loop_iterations_int (struct loop *loop)
  {
 -  double_int nit;
 +  widest_int nit;
    HOST_WIDE_INT hwi_nit;
  
    if (!max_loop_iterations (loop, &nit))
      return -1;
  
 -  if (!nit.fits_shwi ())
 +  if (!wi::fits_shwi_p (nit))
      return -1;
    hwi_nit = nit.to_shwi ();
  
@@@ -3455,18 -3475,18 +3462,18 @@@ estimated_stmt_executions_int (struct l
     false, otherwise returns true.  */
  
  bool
 -max_stmt_executions (struct loop *loop, double_int *nit)
 +max_stmt_executions (struct loop *loop, widest_int *nit)
  {
 -  double_int nit_minus_one;
 +  widest_int nit_minus_one;
  
    if (!max_loop_iterations (loop, nit))
      return false;
  
    nit_minus_one = *nit;
  
 -  *nit += double_int_one;
 +  *nit += 1;
  
 -  return (*nit).ugt (nit_minus_one);
 +  return wi::gtu_p (*nit, nit_minus_one);
  }
  
  /* Sets NIT to the estimated number of executions of the latch of the
     false, otherwise returns true.  */
  
  bool
 -estimated_stmt_executions (struct loop *loop, double_int *nit)
 +estimated_stmt_executions (struct loop *loop, widest_int *nit)
  {
 -  double_int nit_minus_one;
 +  widest_int nit_minus_one;
  
    if (!estimated_loop_iterations (loop, nit))
      return false;
  
    nit_minus_one = *nit;
  
 -  *nit += double_int_one;
 +  *nit += 1;
  
 -  return (*nit).ugt (nit_minus_one);
 +  return wi::gtu_p (*nit, nit_minus_one);
  }
  
  /* Records estimates on numbers of iterations of loops.  */
@@@ -3557,7 -3577,7 +3564,7 @@@ n_of_executions_at_most (gimple stmt
                         struct nb_iter_bound *niter_bound,
                         tree niter)
  {
 -  double_int bound = niter_bound->bound;
 +  widest_int bound = niter_bound->bound;
    tree nit_type = TREE_TYPE (niter), e;
    enum tree_code cmp;
  
  
    /* If the bound does not even fit into NIT_TYPE, it cannot tell us that
       the number of iterations is small.  */
 -  if (!double_int_fits_to_tree_p (nit_type, bound))
 +  if (!wi::fits_to_tree_p (bound, nit_type))
      return false;
  
    /* We know that NITER_BOUND->stmt is executed at most NITER_BOUND->bound + 1
               gsi_next (&bsi))
            if (gimple_has_side_effects (gsi_stmt (bsi)))
               return false;
 -        bound += double_int_one;
 -        if (bound.is_zero ()
 -            || !double_int_fits_to_tree_p (nit_type, bound))
 +        bound += 1;
 +        if (bound == 0
 +            || !wi::fits_to_tree_p (bound, nit_type))
            return false;
        }
        cmp = GT_EXPR;
      }
  
    e = fold_binary (cmp, boolean_type_node,
 -                 niter, double_int_to_tree (nit_type, bound));
 +                 niter, wide_int_to_tree (nit_type, bound));
    return e && integer_nonzerop (e);
  }
  
@@@ -3655,7 -3675,7 +3662,7 @@@ scev_probably_wraps_p (tree base, tree 
    tree unsigned_type, valid_niter;
    tree type = TREE_TYPE (step);
    tree e;
 -  double_int niter;
 +  widest_int niter;
    struct nb_iter_bound *bound;
  
    /* FIXME: We really need something like
    estimate_numbers_of_iterations_loop (loop);
  
    if (max_loop_iterations (loop, &niter)
 -      && double_int_fits_to_tree_p (TREE_TYPE (valid_niter), niter)
 +      && wi::fits_to_tree_p (niter, TREE_TYPE (valid_niter))
        && (e = fold_binary (GT_EXPR, boolean_type_node, valid_niter,
 -                         double_int_to_tree (TREE_TYPE (valid_niter),
 -                                             niter))) != NULL
 +                         wide_int_to_tree (TREE_TYPE (valid_niter),
 +                                           niter))) != NULL
        && integer_nonzerop (e))
      {
        fold_undefer_and_ignore_overflow_warnings ();
index b05a99c68df22986150e05cf819ffad6e0f04c8a,5b7c0c2260c33dfd6c7a6d333c2da806070b19d8..6a84bdc04964970e0b4d21c53f2331fe2b9ed3c0
@@@ -25,7 -25,13 +25,13 @@@ along with GCC; see the file COPYING3
  #include "tm_p.h"
  #include "basic-block.h"
  #include "tree-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-ssa-loop-ivopts.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-into-ssa.h"
  #include "cfgloop.h"
  #include "tree-pass.h"
  #include "insn-config.h"
@@@ -285,7 -291,7 +291,7 @@@ dump_mem_details (FILE *file, tree base
    fprintf (file, "(base ");
    print_generic_expr (file, base, TDF_SLIM);
    fprintf (file, ", step ");
 -  if (cst_and_fits_in_hwi (step))
 +  if (cst_fits_shwi_p (step))
      fprintf (file, HOST_WIDE_INT_PRINT_DEC, int_cst_value (step));
    else
      print_generic_expr (file, step, TDF_TREE);
@@@ -326,7 -332,7 +332,7 @@@ find_or_create_group (struct mem_ref_gr
  
        /* If step is an integer constant, keep the list of groups sorted
           by decreasing step.  */
 -        if (cst_and_fits_in_hwi ((*groups)->step) && cst_and_fits_in_hwi (step)
 +        if (cst_fits_shwi_p ((*groups)->step) && cst_fits_shwi_p (step)
              && int_cst_value ((*groups)->step) < int_cst_value (step))
        break;
      }
@@@ -434,12 -440,12 +440,12 @@@ idx_analyze_ref (tree base, tree *index
    step = iv.step;
  
    if (TREE_CODE (ibase) == POINTER_PLUS_EXPR
 -      && cst_and_fits_in_hwi (TREE_OPERAND (ibase, 1)))
 +      && cst_fits_shwi_p (TREE_OPERAND (ibase, 1)))
      {
        idelta = int_cst_value (TREE_OPERAND (ibase, 1));
        ibase = TREE_OPERAND (ibase, 0);
      }
 -  if (cst_and_fits_in_hwi (ibase))
 +  if (cst_fits_shwi_p (ibase))
      {
        idelta += int_cst_value (ibase);
        ibase = build_int_cst (TREE_TYPE (ibase), 0);
    if (TREE_CODE (base) == ARRAY_REF)
      {
        stepsize = array_ref_element_size (base);
 -      if (!cst_and_fits_in_hwi (stepsize))
 +      if (!cst_fits_shwi_p (stepsize))
        return false;
        imult = int_cst_value (stepsize);
        step = fold_build2 (MULT_EXPR, sizetype,
@@@ -505,7 -511,7 +511,7 @@@ analyze_ref (struct loop *loop, tree *r
    for (; TREE_CODE (ref) == COMPONENT_REF; ref = TREE_OPERAND (ref, 0))
      {
        off = DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1));
 -      bit_offset = TREE_INT_CST_LOW (off);
 +      bit_offset = tree_to_hwi (off);
        gcc_assert (bit_offset % BITS_PER_UNIT == 0);
  
        *delta += bit_offset / BITS_PER_UNIT;
@@@ -546,7 -552,7 +552,7 @@@ gather_memory_references_ref (struct lo
  
    /* Limit non-constant step prefetching only to the innermost loops and 
       only when the step is loop invariant in the entire loop nest. */
 -  if (!cst_and_fits_in_hwi (step))
 +  if (!cst_fits_shwi_p (step))
      {
        if (loop->inner != NULL)
          {
@@@ -660,7 -666,7 +666,7 @@@ prune_ref_by_self_reuse (struct mem_re
    bool backward;
  
    /* If the step size is non constant, we cannot calculate prefetch_mod.  */
 -  if (!cst_and_fits_in_hwi (ref->group->step))
 +  if (!cst_fits_shwi_p (ref->group->step))
      return;
  
    step = int_cst_value (ref->group->step);
@@@ -770,7 -776,7 +776,7 @@@ prune_ref_by_group_reuse (struct mem_re
    int align_unit;
  
    /* If the step is non constant we cannot calculate prefetch_before.  */
 -  if (!cst_and_fits_in_hwi (ref->group->step)) {
 +  if (!cst_fits_shwi_p (ref->group->step)) {
      return;
    }
  
@@@ -1135,7 -1141,7 +1141,7 @@@ issue_prefetch_ref (struct mem_ref *ref
  
    for (ap = 0; ap < n_prefetches; ap++)
      {
 -      if (cst_and_fits_in_hwi (ref->group->step))
 +      if (cst_fits_shwi_p (ref->group->step))
          {
            /* Determine the address to prefetch.  */
            delta = (ahead + ap * ref->prefetch_mod) *
@@@ -1449,8 -1455,8 +1455,8 @@@ add_subscript_strides (tree access_fn, 
        if ((unsigned) loop_depth (aloop) <= min_depth)
        continue;
  
 -      if (host_integerp (step, 0))
 -      astep = tree_low_cst (step, 0);
 +      if (tree_fits_shwi_p (step))
 +      astep = tree_to_shwi (step);
        else
        astep = L1_CACHE_LINE_SIZE;
  
@@@ -1499,8 -1505,8 +1505,8 @@@ self_reuse_distance (data_reference_p d
        if (TREE_CODE (ref) == ARRAY_REF)
        {
          stride = TYPE_SIZE_UNIT (TREE_TYPE (ref));
 -        if (host_integerp (stride, 1))
 -          astride = tree_low_cst (stride, 1);
 +        if (tree_fits_uhwi_p (stride))
 +          astride = tree_to_uhwi (stride);
          else
            astride = L1_CACHE_LINE_SIZE;
  
diff --combined gcc/tree-ssa-loop.h
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
@@@ -54,7 -49,7 +51,7 @@@ struct tree_niter_des
                           a loop (provided that assumptions == true and
                           may_be_zero == false), more precisely the number
                           of executions of the latch of the loop.  */
 -  double_int max;     /* The upper bound on the number of iterations of
 +  widest_int max;     /* The upper bound on the number of iterations of
                           the loop.  */
  
    /* The simplified shape of the exit condition.  The loop exits if
diff --combined gcc/tree-ssa-math-opts.c
index e7a489d6e77f83ab3d50561d5f1999af25830d60,9a2941119458621408aa1e6a7d40fbed14a7e97c..b338f63eb5ffa3cc61cb4f6f4fc293f39483e3ae
@@@ -90,6 -90,13 +90,13 @@@ along with GCC; see the file COPYING3
  #include "tm.h"
  #include "flags.h"
  #include "tree.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "tree-pass.h"
  #include "alloc-pool.h"
@@@ -1139,7 -1146,7 +1146,7 @@@ gimple_expand_builtin_pow (gimple_stmt_
       multiplication sequence when profitable.  */
    c = TREE_REAL_CST (arg1);
    n = real_to_integer (&c);
 -  real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
 +  real_from_integer (&cint, VOIDmode, n, SIGNED);
    c_is_int = real_identical (&c, &cint);
  
    if (c_is_int
    /* Optimize pow(x,0.75) = sqrt(x) * sqrt(sqrt(x)) unless we are
       optimizing for space.  Don't do this optimization if we don't have
       a hardware sqrt insn.  */
 -  real_from_integer (&dconst3_4, VOIDmode, 3, 0, 0);
 +  real_from_integer (&dconst3_4, VOIDmode, 3, SIGNED);
    SET_REAL_EXP (&dconst3_4, REAL_EXP (&dconst3_4) - 2);
  
    if (flag_unsafe_math_optimizations
       Do not calculate the powi factor when n/2 = 0.  */
    real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
    n = real_to_integer (&c2);
 -  real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
 +  real_from_integer (&cint, VOIDmode, n, SIGNED);
    c2_is_int = real_identical (&c2, &cint);
  
    if (flag_unsafe_math_optimizations
       different from pow(x, 1./3.) due to rounding and behavior with
       negative x, we need to constrain this transformation to unsafe
       math and positive x or finite math.  */
 -  real_from_integer (&dconst3, VOIDmode, 3, 0, 0);
 +  real_from_integer (&dconst3, VOIDmode, 3, SIGNED);
    real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
    real_round (&c2, mode, &c2);
    n = real_to_integer (&c2);
 -  real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
 +  real_from_integer (&cint, VOIDmode, n, SIGNED);
    real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
    real_convert (&c2, mode, &c2);
  
@@@ -1493,10 -1500,10 +1500,10 @@@ execute_cse_sincos (void
                    }
                  else
                    {
 -                    if (!host_integerp (arg1, 0))
 +                    if (!tree_fits_shwi_p (arg1))
                        break;
 -
 -                    n = TREE_INT_CST_LOW (arg1);
 +                    
 +                    n = tree_to_shwi (arg1);
                      result = gimple_expand_builtin_powi (&gsi, loc, arg0, n);
                    }
  
@@@ -1754,7 -1761,7 +1761,7 @@@ find_bswap_1 (gimple stmt, struct symbo
        case RSHIFT_EXPR:
        case LROTATE_EXPR:
        case RROTATE_EXPR:
 -        if (!do_shift_rotate (code, n, (int)TREE_INT_CST_LOW (rhs2)))
 +        if (!do_shift_rotate (code, n, (int)tree_to_hwi (rhs2)))
            return NULL_TREE;
          break;
        CASE_CONVERT:
@@@ -1847,7 -1854,7 +1854,7 @@@ find_bswap (gimple stmt
       increase that number by three  here in order to also
       cover signed -> unsigned converions of the src operand as can be seen
       in libgcc, and for initial shift/and operation of the src operand.  */
 -  limit = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (gimple_expr_type (stmt)));
 +  limit = tree_to_hwi (TYPE_SIZE_UNIT (gimple_expr_type (stmt)));
    limit += 1 + (int) ceil_log2 ((unsigned HOST_WIDE_INT) limit);
    source_expr =  find_bswap_1 (stmt, &n, limit);
  
@@@ -2425,20 -2432,25 +2432,25 @@@ convert_plusminus_to_widen (gimple_stmt
  
       It might also appear that it would be sufficient to use the existing
       operands of the widening multiply, but that would limit the choice of
-      multiply-and-accumulate instructions.  */
+      multiply-and-accumulate instructions.
+      If the widened-multiplication result has more than one uses, it is
+      probably wiser not to do the conversion.  */
    if (code == PLUS_EXPR
        && (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR))
      {
-       if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
-                              &type2, &mult_rhs2))
+       if (!has_single_use (rhs1)
+         || !is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
+                                 &type2, &mult_rhs2))
        return false;
        add_rhs = rhs2;
        conv_stmt = conv1_stmt;
      }
    else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
      {
-       if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
-                              &type2, &mult_rhs2))
+       if (!has_single_use (rhs2)
+         || !is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
+                                 &type2, &mult_rhs2))
        return false;
        add_rhs = rhs1;
        conv_stmt = conv2_stmt;
diff --combined gcc/tree-ssa-phiopt.c
index 9435cc1b10c3b3bf28f3d73db30990ec7c97c9f0,ef114a01a6dd8438b1b67d08d6c2e5e8177b84b4..5e8a7ce57a562aae5c74a95e19441596aa6022cb
@@@ -27,7 -27,13 +27,13 @@@ along with GCC; see the file COPYING3
  #include "flags.h"
  #include "tm_p.h"
  #include "basic-block.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "tree-pass.h"
  #include "langhooks.h"
  #include "pointer-set.h"
@@@ -679,7 -685,7 +685,7 @@@ jump_function_from_stmt (tree *arg, gim
                                                &offset);
        if (tem
          && TREE_CODE (tem) == MEM_REF
 -        && (mem_ref_offset (tem) + double_int::from_shwi (offset)).is_zero ())
 +        && (mem_ref_offset (tem) + offset) == 0)
        {
          *arg = TREE_OPERAND (tem, 0);
          return true;
@@@ -1351,7 -1357,7 +1357,7 @@@ add_or_mark_expr (basic_block bb, tree 
  
    if (TREE_CODE (exp) == MEM_REF
        && TREE_CODE (TREE_OPERAND (exp, 0)) == SSA_NAME
 -      && host_integerp (TREE_OPERAND (exp, 1), 0)
 +      && tree_fits_shwi_p (TREE_OPERAND (exp, 1))
        && (size = int_size_in_bytes (TREE_TYPE (exp))) > 0)
      {
        tree name = TREE_OPERAND (exp, 0);
        map.phase = 0;
        map.bb = 0;
        map.store = store;
 -      map.offset = tree_low_cst (TREE_OPERAND (exp, 1), 0);
 +      map.offset = tree_to_shwi (TREE_OPERAND (exp, 1));
        map.size = size;
  
        slot = seen_ssa_names.find_slot (&map, INSERT);
@@@ -1674,7 -1680,6 +1680,6 @@@ cond_if_else_store_replacement (basic_b
    data_reference_p then_dr, else_dr;
    int i, j;
    tree then_lhs, else_lhs;
-   vec<gimple> then_stores, else_stores;
    basic_block blocks[3];
  
    if (MAX_STORES_TO_SINK == 0)
      }
  
    /* Find pairs of stores with equal LHS.  */
-   then_stores.create (1);
-   else_stores.create (1);
+   stack_vec<gimple, 1> then_stores, else_stores;
    FOR_EACH_VEC_ELT (then_datarefs, i, then_dr)
      {
        if (DR_IS_READ (then_dr))
      {
        free_data_refs (then_datarefs);
        free_data_refs (else_datarefs);
-       then_stores.release ();
-       else_stores.release ();
        return false;
      }
  
        free_dependence_relations (else_ddrs);
        free_data_refs (then_datarefs);
        free_data_refs (else_datarefs);
-       then_stores.release ();
-       else_stores.release ();
        return false;
      }
    blocks[0] = then_bb;
            free_dependence_relations (else_ddrs);
          free_data_refs (then_datarefs);
          free_data_refs (else_datarefs);
-           then_stores.release ();
-           else_stores.release ();
            return false;
          }
      }
            free_dependence_relations (else_ddrs);
          free_data_refs (then_datarefs);
          free_data_refs (else_datarefs);
-           then_stores.release ();
-           else_stores.release ();
            return false;
          }
      }
    free_dependence_relations (else_ddrs);
    free_data_refs (then_datarefs);
    free_data_refs (else_datarefs);
-   then_stores.release ();
-   else_stores.release ();
  
    return ok;
  }
@@@ -1978,14 -1972,14 +1972,14 @@@ hoist_adjacent_loads (basic_block bb0, 
        tree_offset2 = bit_position (field2);
        tree_size2 = DECL_SIZE (field2);
  
 -      if (!host_integerp (tree_offset1, 1)
 -        || !host_integerp (tree_offset2, 1)
 -        || !host_integerp (tree_size2, 1))
 +      if (!tree_fits_uhwi_p (tree_offset1)
 +        || !tree_fits_uhwi_p (tree_offset2)
 +        || !tree_fits_uhwi_p (tree_size2))
        continue;
  
 -      offset1 = TREE_INT_CST_LOW (tree_offset1);
 -      offset2 = TREE_INT_CST_LOW (tree_offset2);
 -      size2 = TREE_INT_CST_LOW (tree_size2);
 +      offset1 = tree_to_uhwi (tree_offset1);
 +      offset2 = tree_to_uhwi (tree_offset2);
 +      size2 = tree_to_uhwi (tree_size2);
        align1 = DECL_ALIGN (field1) % param_align_bits;
  
        if (offset1 % BITS_PER_UNIT != 0)
diff --combined gcc/tree-ssa-pre.c
index ac8d528ef8d2931758a099c26007af43e052480c,4d97b13c999a4bf444a7f9a4c7cb6d7caf595eee..a5d54877ff2dabc409d206d1eccc7735fb4545ec
@@@ -27,15 -27,22 +27,22 @@@ along with GCC; see the file COPYING3
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
  #include "tree-inline.h"
- #include "tree-ssa.h"
  #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-into-ssa.h"
+ #include "tree-dfa.h"
+ #include "tree-ssa.h"
  #include "hash-table.h"
  #include "tree-iterator.h"
  #include "alloc-pool.h"
  #include "obstack.h"
  #include "tree-pass.h"
  #include "flags.h"
- #include "bitmap.h"
  #include "langhooks.h"
  #include "cfgloop.h"
  #include "tree-ssa-sccvn.h"
@@@ -1581,11 -1588,11 +1588,11 @@@ phi_translate_1 (pre_expr expr, bitmap_
                && TREE_CODE (op[1]) == INTEGER_CST
                && TREE_CODE (op[2]) == INTEGER_CST)
              {
 -              double_int off = tree_to_double_int (op[0]);
 -              off += -tree_to_double_int (op[1]);
 -              off *= tree_to_double_int (op[2]);
 -              if (off.fits_shwi ())
 -                newop.off = off.low;
 +              offset_int off = ((wi::to_offset (op[0])
 +                                 - wi::to_offset (op[1]))
 +                                * wi::to_offset (op[2]));
 +              if (wi::fits_shwi_p (off))
 +                newop.off = off.to_shwi ();
              }
            newoperands[j] = newop;
            /* If it transforms from an SSA_NAME to an address, fold with
diff --combined gcc/tree-ssa-reassoc.c
index 2533aedfae2be4e01159081d39b819d97c7307cc,538a8ef0e4a25e874b97ff9dc1f772544b2f3b53..df34bc29ffcbbf9780b9e79cfb50a7ec224ff65a
@@@ -29,8 -29,16 +29,16 @@@ along with GCC; see the file COPYING3
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
  #include "tree-inline.h"
- #include "tree-ssa.h"
  #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-dfa.h"
+ #include "tree-ssa.h"
  #include "tree-iterator.h"
  #include "tree-pass.h"
  #include "alloc-pool.h"
@@@ -1038,13 -1046,13 +1046,13 @@@ decrement_power (gimple stmt
        arg1 = gimple_call_arg (stmt, 1);
        c = TREE_REAL_CST (arg1);
        power = real_to_integer (&c) - 1;
 -      real_from_integer (&cint, VOIDmode, power, 0, 0);
 +      real_from_integer (&cint, VOIDmode, power, SIGNED);
        gimple_call_set_arg (stmt, 1, build_real (TREE_TYPE (arg1), cint));
        return power;
  
      CASE_FLT_FN (BUILT_IN_POWI):
        arg1 = gimple_call_arg (stmt, 1);
 -      power = TREE_INT_CST_LOW (arg1) - 1;
 +      power = tree_to_hwi (arg1) - 1;
        gimple_call_set_arg (stmt, 1, build_int_cst (TREE_TYPE (arg1), power));
        return power;
  
@@@ -1143,12 -1151,94 +1151,94 @@@ zero_one_operation (tree *def, enum tre
    while (1);
  }
  
- /* Returns the UID of STMT if it is non-NULL. Otherwise return 1.  */
+ /* Returns true if statement S1 dominates statement S2.  Like
+    stmt_dominates_stmt_p, but uses stmt UIDs to optimize.  */
  
- static inline unsigned
get_stmt_uid_with_default (gimple stmt)
+ static bool
reassoc_stmt_dominates_stmt_p (gimple s1, gimple s2)
  {
-   return stmt ? gimple_uid (stmt) : 1;
+   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
+      SSA_NAME.  Assume it lives at the beginning of function and
+      thus dominates everything.  */
+   if (!bb1 || s1 == s2)
+     return true;
+   /* If bb2 is NULL, it doesn't dominate any stmt with a bb.  */
+   if (!bb2)
+     return false;
+   if (bb1 == bb2)
+     {
+       /* PHIs in the same basic block are assumed to be
+        executed all in parallel, if only one stmt is a PHI,
+        it dominates the other stmt in the same basic block.  */
+       if (gimple_code (s1) == GIMPLE_PHI)
+       return true;
+       if (gimple_code (s2) == GIMPLE_PHI)
+       return false;
+       gcc_assert (gimple_uid (s1) && gimple_uid (s2));
+       if (gimple_uid (s1) < gimple_uid (s2))
+       return true;
+       if (gimple_uid (s1) > gimple_uid (s2))
+       return false;
+       gimple_stmt_iterator gsi = gsi_for_stmt (s1);
+       unsigned int uid = gimple_uid (s1);
+       for (gsi_next (&gsi); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple s = gsi_stmt (gsi);
+         if (gimple_uid (s) != uid)
+           break;
+         if (s == s2)
+           return true;
+       }
+       return false;
+     }
+   return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
+ }
+ /* Insert STMT after INSERT_POINT.  */
+ static void
+ insert_stmt_after (gimple stmt, gimple insert_point)
+ {
+   gimple_stmt_iterator gsi;
+   basic_block bb;
+   if (gimple_code (insert_point) == GIMPLE_PHI)
+     bb = gimple_bb (insert_point);
+   else if (!stmt_ends_bb_p (insert_point))
+     {
+       gsi = gsi_for_stmt (insert_point);
+       gimple_set_uid (stmt, gimple_uid (insert_point));
+       gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+       return;
+     }
+   else
+     /* We assume INSERT_POINT is a SSA_NAME_DEF_STMT of some SSA_NAME,
+        thus if it must end a basic block, it should be a call that can
+        throw, or some assignment that can throw.  If it throws, the LHS
+        of it will not be initialized though, so only valid places using
+        the SSA_NAME should be dominated by the fallthru edge.  */
+     bb = find_fallthru_edge (gimple_bb (insert_point)->succs)->dest;
+   gsi = gsi_after_labels (bb);
+   if (gsi_end_p (gsi))
+     {
+       gimple_stmt_iterator gsi2 = gsi_last_bb (bb);
+       gimple_set_uid (stmt,
+                     gsi_end_p (gsi2) ? 1 : gimple_uid (gsi_stmt (gsi2)));
+     }
+   else
+     gimple_set_uid (stmt, gimple_uid (gsi_stmt (gsi)));
+   gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
  }
  
  /* Builds one statement performing OP1 OPCODE OP2 using TMPVAR for
@@@ -1176,64 -1266,27 +1266,27 @@@ build_and_add_sum (tree type, tree op1
        && (!op2def || gimple_nop_p (op2def)))
      {
        gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
-       gimple_set_uid (sum, get_stmt_uid_with_default (gsi_stmt (gsi)));
-       gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
-     }
-   else if ((!op1def || gimple_nop_p (op1def))
-          || (op2def && !gimple_nop_p (op2def)
-              && stmt_dominates_stmt_p (op1def, op2def)))
-     {
-       if (gimple_code (op2def) == GIMPLE_PHI)
+       if (gsi_end_p (gsi))
        {
-         gsi = gsi_after_labels (gimple_bb (op2def));
-           gimple_set_uid (sum, get_stmt_uid_with_default (gsi_stmt (gsi)));
-         gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
+         gimple_stmt_iterator gsi2
+           = gsi_last_bb (single_succ (ENTRY_BLOCK_PTR));
+         gimple_set_uid (sum,
+                         gsi_end_p (gsi2) ? 1 : gimple_uid (gsi_stmt (gsi2)));
        }
        else
-       {
-         if (!stmt_ends_bb_p (op2def))
-           {
-             gsi = gsi_for_stmt (op2def);
-               gimple_set_uid (sum, gimple_uid (op2def));
-             gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
-           }
-         else
-           {
-             edge e;
-             edge_iterator ei;
-             FOR_EACH_EDGE (e, ei, gimple_bb (op2def)->succs)
-               if (e->flags & EDGE_FALLTHRU)
-                 gsi_insert_on_edge_immediate (e, sum);
-           }
-       }
+       gimple_set_uid (sum, gimple_uid (gsi_stmt (gsi)));
+       gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
      }
    else
      {
-       if (gimple_code (op1def) == GIMPLE_PHI)
-       {
-         gsi = gsi_after_labels (gimple_bb (op1def));
-           gimple_set_uid (sum, get_stmt_uid_with_default (gsi_stmt (gsi)));
-         gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
-       }
+       gimple insert_point;
+       if ((!op1def || gimple_nop_p (op1def))
+          || (op2def && !gimple_nop_p (op2def)
+              && reassoc_stmt_dominates_stmt_p (op1def, op2def)))
+       insert_point = op2def;
        else
-       {
-         if (!stmt_ends_bb_p (op1def))
-           {
-             gsi = gsi_for_stmt (op1def);
-               gimple_set_uid (sum, gimple_uid (op1def));
-             gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
-           }
-         else
-           {
-             edge e;
-             edge_iterator ei;
-             FOR_EACH_EDGE (e, ei, gimple_bb (op1def)->succs)
-               if (e->flags & EDGE_FALLTHRU)
-                 gsi_insert_on_edge_immediate (e, sum);
-           }
-       }
+       insert_point = op1def;
+       insert_stmt_after (sum, insert_point);
      }
    update_stmt (sum);
  
@@@ -1954,8 -2007,8 +2007,8 @@@ range_entry_cmp (const void *a, const v
     true if the range merge has been successful.
     If OPCODE is ERROR_MARK, this is called from within
     maybe_optimize_range_tests and is performing inter-bb range optimization.
-    Changes should be then performed right away, and whether an op is
-    BIT_AND_EXPR or BIT_IOR_EXPR is found in oe->rank.  */
+    In that case, whether an op is BIT_AND_EXPR or BIT_IOR_EXPR is found in
+    oe->rank.  */
  
  static bool
  update_range_test (struct range_entry *range, struct range_entry *otherrange,
    gsi = gsi_for_stmt (stmt);
    tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true,
                                  GSI_SAME_STMT);
+   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+     if (gimple_uid (gsi_stmt (gsi)))
+       break;
+     else
+       gimple_set_uid (gsi_stmt (gsi), gimple_uid (stmt));
  
-   /* If doing inter-bb range test optimization, update the
-      stmts immediately.  Start with changing the first range test
-      immediate use to the new value (TEM), or, if the first range
-      test is a GIMPLE_COND stmt, change that condition.  */
-   if (opcode == ERROR_MARK)
-     {
-       if (op)
-       {
-         imm_use_iterator iter;
-         use_operand_p use_p;
-         gimple use_stmt;
-         FOR_EACH_IMM_USE_STMT (use_stmt, iter, op)
-           {
-             if (is_gimple_debug (use_stmt))
-               continue;
-             FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
-               SET_USE (use_p, tem);
-             update_stmt (use_stmt);
-           }
-       }
-       else
-       {
-         gimple_cond_set_code (stmt, NE_EXPR);
-         gimple_cond_set_lhs (stmt, tem);
-         gimple_cond_set_rhs (stmt, boolean_false_node);
-         update_stmt (stmt);
-       }
-     }
    oe->op = tem;
    range->exp = exp;
    range->low = low;
        if (opcode == ERROR_MARK)
        {
          if (oe->op)
-           {
-             imm_use_iterator iter;
-             use_operand_p use_p;
-             gimple use_stmt;
-             FOR_EACH_IMM_USE_STMT (use_stmt, iter, oe->op)
-               {
-                 if (is_gimple_debug (use_stmt))
-                   continue;
-                 /* If imm use of _8 is a statement like _7 = _8 | _9;,
-                    adjust it into _7 = _9;.  */
-                 if (is_gimple_assign (use_stmt)
-                     && gimple_assign_rhs_code (use_stmt) == oe->rank)
-                   {
-                     tree expr = NULL_TREE;
-                     if (oe->op == gimple_assign_rhs1 (use_stmt))
-                       expr = gimple_assign_rhs2 (use_stmt);
-                     else if (oe->op == gimple_assign_rhs2 (use_stmt))
-                       expr = gimple_assign_rhs1 (use_stmt);
-                     if (expr
-                         && expr != oe->op
-                         && TREE_CODE (expr) == SSA_NAME)
-                       {
-                         gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
-                         gimple_assign_set_rhs_with_ops (&gsi2, SSA_NAME,
-                                                         expr, NULL_TREE);
-                         update_stmt (use_stmt);
-                         continue;
-                       }
-                   }
-                 /* If imm use of _8 is a statement like _7 = (int) _8;,
-                    adjust it into _7 = 0; or _7 = 1;.  */
-                 if (gimple_assign_cast_p (use_stmt)
-                     && oe->op == gimple_assign_rhs1 (use_stmt))
-                   {
-                     tree lhs = gimple_assign_lhs (use_stmt);
-                     if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
-                       {
-                         gimple_stmt_iterator gsi2
-                           = gsi_for_stmt (use_stmt);
-                         tree expr = build_int_cst (TREE_TYPE (lhs),
-                                                    oe->rank == BIT_IOR_EXPR
-                                                    ? 0 : 1);
-                         gimple_assign_set_rhs_with_ops (&gsi2,
-                                                         INTEGER_CST,
-                                                         expr, NULL_TREE);
-                         update_stmt (use_stmt);
-                         continue;
-                       }
-                   }
-                 /* Otherwise replace the use with 0 or 1.  */
-                 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
-                   SET_USE (use_p,
-                            build_int_cst (TREE_TYPE (oe->op),
-                                           oe->rank == BIT_IOR_EXPR
-                                           ? 0 : 1));
-                 update_stmt (use_stmt);
-               }
-           }
+           oe->op = build_int_cst (TREE_TYPE (oe->op),
+                                   oe->rank == BIT_IOR_EXPR ? 0 : 1);
          else
-           {
-             /* If range test was a GIMPLE_COND, simply change it
-                into an always false or always true condition.  */
-             stmt = last_stmt (BASIC_BLOCK (oe->id));
-             if (oe->rank == BIT_IOR_EXPR)
-               gimple_cond_make_false (stmt);
-             else
-               gimple_cond_make_true (stmt);
-             update_stmt (stmt);
-           }
+           oe->op = (oe->rank == BIT_IOR_EXPR
+                     ? boolean_false_node : boolean_true_node);
        }
-       oe->op = error_mark_node;
+       else
+       oe->op = error_mark_node;
        range->exp = NULL_TREE;
      }
    return true;
@@@ -2288,7 -2253,7 +2253,7 @@@ optimize_range_tests_1 (enum tree_code 
     GIMPLE_COND is && or ||ed into the test, and oe->rank says
     the actual opcode.  */
  
- static void
+ static bool
  optimize_range_tests (enum tree_code opcode,
                      vec<operand_entry_t> *ops)
  {
    bool any_changes = false;
  
    if (length == 1)
-     return;
+     return false;
  
    ranges = XNEWVEC (struct range_entry, length);
    for (i = 0; i < length; i++)
      }
  
    XDELETEVEC (ranges);
+   return any_changes;
  }
  
  /* Return true if STMT is a cast like:
@@@ -2624,6 -2590,60 +2590,60 @@@ get_ops (tree var, enum tree_code code
    return true;
  }
  
+ /* Find the ops that were added by get_ops starting from VAR, see if
+    they were changed during update_range_test and if yes, create new
+    stmts.  */
+ static tree
+ update_ops (tree var, enum tree_code code, vec<operand_entry_t> ops,
+           unsigned int *pidx, struct loop *loop)
+ {
+   gimple stmt = SSA_NAME_DEF_STMT (var);
+   tree rhs[4];
+   int i;
+   if (!is_reassociable_op (stmt, code, loop))
+     return NULL;
+   rhs[0] = gimple_assign_rhs1 (stmt);
+   rhs[1] = gimple_assign_rhs2 (stmt);
+   rhs[2] = rhs[0];
+   rhs[3] = rhs[1];
+   for (i = 0; i < 2; i++)
+     if (TREE_CODE (rhs[i]) == SSA_NAME)
+       {
+       rhs[2 + i] = update_ops (rhs[i], code, ops, pidx, loop);
+       if (rhs[2 + i] == NULL_TREE)
+         {
+           if (has_single_use (rhs[i]))
+             rhs[2 + i] = ops[(*pidx)++]->op;
+           else
+             rhs[2 + i] = rhs[i];
+         }
+       }
+   if ((rhs[2] != rhs[0] || rhs[3] != rhs[1])
+       && (rhs[2] != rhs[1] || rhs[3] != rhs[0]))
+     {
+       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+       var = make_ssa_name (TREE_TYPE (var), NULL);
+       gimple g = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt),
+                                              var, rhs[2], rhs[3]);
+       gimple_set_uid (g, gimple_uid (stmt));
+       gimple_set_visited (g, true);
+       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+     }
+   return var;
+ }
+ /* Structure to track the initial value passed to get_ops and
+    the range in the ops vector for each basic block.  */
+ struct inter_bb_range_test_entry
+ {
+   tree op;
+   unsigned int first_idx, last_idx;
+ };
  /* Inter-bb range test optimization.  */
  
  static void
@@@ -2636,6 -2656,8 +2656,8 @@@ maybe_optimize_range_tests (gimple stmt
    edge_iterator ei;
    edge e;
    vec<operand_entry_t> ops = vNULL;
+   vec<inter_bb_range_test_entry> bbinfo = vNULL;
+   bool any_changes = false;
  
    /* Consider only basic blocks that end with GIMPLE_COND or
       a cast statement satisfying final_range_test_p.  All
      {
        enum tree_code code;
        tree lhs, rhs;
+       inter_bb_range_test_entry bb_ent;
  
+       bb_ent.op = NULL_TREE;
+       bb_ent.first_idx = ops.length ();
+       bb_ent.last_idx = bb_ent.first_idx;
        e = find_edge (bb, other_bb);
        stmt = last_stmt (bb);
        gimple_set_visited (stmt, true);
              oe->id = 0;
              oe->count = 1;
              ops.safe_push (oe);
+             bb_ent.last_idx++;
            }
+         else
+           bb_ent.last_idx = ops.length ();
+         bb_ent.op = rhs;
+         bbinfo.safe_push (bb_ent);
          continue;
        }
        /* Otherwise stmt is GIMPLE_COND.  */
          oe->id = bb->index;
          oe->count = 1;
          ops.safe_push (oe);
+         bb_ent.op = NULL;
+         bb_ent.last_idx++;
        }
+       else if (ops.length () > bb_ent.first_idx)
+       {
+         bb_ent.op = lhs;
+         bb_ent.last_idx = ops.length ();
+       }
+       bbinfo.safe_push (bb_ent);
        if (bb == first_bb)
        break;
      }
    if (ops.length () > 1)
-     optimize_range_tests (ERROR_MARK, &ops);
+     any_changes = optimize_range_tests (ERROR_MARK, &ops);
+   if (any_changes)
+     {
+       unsigned int idx;
+       /* update_ops relies on has_single_use predicates returning the
+        same values as it did during get_ops earlier.  Additionally it
+        never removes statements, only adds new ones and it should walk
+        from the single imm use and check the predicate already before
+        making those changes.
+        On the other side, the handling of GIMPLE_COND directly can turn
+        previously multiply used SSA_NAMEs into single use SSA_NAMEs, so
+        it needs to be done in a separate loop afterwards.  */
+       for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
+       {
+         if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
+             && bbinfo[idx].op != NULL_TREE)
+           {
+             tree new_op;
+             stmt = last_stmt (bb);
+             new_op = update_ops (bbinfo[idx].op,
+                                  (enum tree_code)
+                                  ops[bbinfo[idx].first_idx]->rank,
+                                  ops, &bbinfo[idx].first_idx,
+                                  loop_containing_stmt (stmt));
+             if (new_op == NULL_TREE)
+               {
+                 gcc_assert (bb == last_bb);
+                 new_op = ops[bbinfo[idx].first_idx++]->op;
+               }
+             if (bbinfo[idx].op != new_op)
+               {
+                 imm_use_iterator iter;
+                 use_operand_p use_p;
+                 gimple use_stmt, cast_stmt = NULL;
+                 FOR_EACH_IMM_USE_STMT (use_stmt, iter, bbinfo[idx].op)
+                   if (is_gimple_debug (use_stmt))
+                     continue;
+                   else if (gimple_code (use_stmt) == GIMPLE_COND
+                            || gimple_code (use_stmt) == GIMPLE_PHI)
+                     FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+                       SET_USE (use_p, new_op);
+                   else if (gimple_assign_cast_p (use_stmt))
+                     cast_stmt = use_stmt;
+                   else
+                     gcc_unreachable ();
+                 if (cast_stmt)
+                   {
+                     gcc_assert (bb == last_bb);
+                     tree lhs = gimple_assign_lhs (cast_stmt);
+                     tree new_lhs = make_ssa_name (TREE_TYPE (lhs), NULL);
+                     enum tree_code rhs_code
+                       = gimple_assign_rhs_code (cast_stmt);
+                     gimple g
+                       = gimple_build_assign_with_ops (rhs_code, new_lhs,
+                                                       new_op, NULL_TREE);
+                     gimple_stmt_iterator gsi = gsi_for_stmt (cast_stmt);
+                     gimple_set_uid (g, gimple_uid (cast_stmt));
+                     gimple_set_visited (g, true);
+                     gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+                     FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
+                       if (is_gimple_debug (use_stmt))
+                         continue;
+                       else if (gimple_code (use_stmt) == GIMPLE_COND
+                                || gimple_code (use_stmt) == GIMPLE_PHI)
+                         FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+                           SET_USE (use_p, new_lhs);
+                       else
+                         gcc_unreachable ();
+                   }
+               }
+           }
+         if (bb == first_bb)
+           break;
+       }
+       for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
+       {
+         if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
+             && bbinfo[idx].op == NULL_TREE
+             && ops[bbinfo[idx].first_idx]->op != NULL_TREE)
+           {
+             stmt = last_stmt (bb);
+             if (integer_zerop (ops[bbinfo[idx].first_idx]->op))
+               gimple_cond_make_false (stmt);
+             else if (integer_onep (ops[bbinfo[idx].first_idx]->op))
+               gimple_cond_make_true (stmt);
+             else
+               {
+                 gimple_cond_set_code (stmt, NE_EXPR);
+                 gimple_cond_set_lhs (stmt, ops[bbinfo[idx].first_idx]->op);
+                 gimple_cond_set_rhs (stmt, boolean_false_node);
+               }
+             update_stmt (stmt);
+           }
+         if (bb == first_bb)
+           break;
+       }
+     }
+   bbinfo.release ();
    ops.release ();
  }
  
@@@ -2941,175 -3079,36 +3079,36 @@@ swap_ops_for_binary_stmt (vec<operand_e
        oe2->op = oe1->op;
        oe2->rank = oe1->rank;
        oe1->op = temp.op;
-       oe1->rank= temp.rank;
-     }
- }
- /* Determine if stmt A is not dominated by stmt B. If A and B are in
-    same basic block, then A's UID has to be less than B. If they are
-    in different BB's, then A's BB must not be dominated by B's BB.  */
- static inline bool
- not_dominated_by (gimple a, gimple b)
- {
-   basic_block bb_a, bb_b;
-   bb_a = gimple_bb (a);
-   bb_b = gimple_bb (b);
-   return ((bb_a == bb_b && gimple_uid (a) < gimple_uid (b))
-           || (bb_a != bb_b
-               && !dominated_by_p (CDI_DOMINATORS, bb_a, bb_b)));
- }
- /* Among STMT1 and STMT2, return the statement that appears later. Both
-    statements are in same BB and have the same UID.  */
- static gimple
- appears_later_in_bb (gimple stmt1, gimple stmt2)
- {
-   unsigned uid = gimple_uid (stmt1);
-   gimple_stmt_iterator gsi = gsi_for_stmt (stmt1);
-   for (gsi_next (&gsi); !gsi_end_p (gsi); gsi_next (&gsi))
-     {
-       gimple stmt = gsi_stmt (gsi);
-       /* If STMT has a different UID than STMT1 and we haven't seen
-          STMT2 during traversal, we know STMT1 appears later.  */
-       if (gimple_uid (stmt) != uid)
-         return stmt1;
-       else if (stmt == stmt2)
-         return stmt2;
+       oe1->rank = temp.rank;
      }
-   return stmt1;
  }
  
- /* Find the statement after which STMT must be moved so that the
-    dependency from DEP_STMT to STMT is maintained.  */
- static gimple
- find_insert_point (gimple stmt, gimple dep_stmt)
- {
-   gimple insert_stmt = stmt;
-   if (dep_stmt == NULL)
-     return stmt;
-   if (gimple_uid (insert_stmt) == gimple_uid (dep_stmt)
-       && gimple_bb (insert_stmt) == gimple_bb (dep_stmt)
-       && insert_stmt != dep_stmt)
-     insert_stmt = appears_later_in_bb (insert_stmt, dep_stmt);
-   else if (not_dominated_by (insert_stmt, dep_stmt))
-     insert_stmt = dep_stmt;
-   return insert_stmt;
- }
- /* Insert STMT after INSERT_POINT.  */
- static void
- insert_stmt_after (gimple stmt, gimple insert_point)
- {
-   imm_use_iterator iter;
-   tree lhs;
-   gimple use_stmt;
-   gimple_stmt_iterator gsistmt = gsi_for_stmt (stmt), gsi_insert;
-   basic_block insert_bb = gimple_bb (insert_point);
-   bool insert_bb_different = (insert_bb != gimple_bb (stmt));
-   lhs = gimple_assign_lhs (stmt);
-   /* If there are any debug uses of LHS, reset them.  */
-   FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
-     {
-       if (is_gimple_debug (use_stmt)
-           && not_dominated_by (use_stmt, insert_point))
-         {
-           gimple_debug_bind_reset_value (use_stmt);
-           update_stmt (use_stmt);
-         }
-     }
-   /* If INSERT_STMT is a phi node, then do not insert just after that statement.
-      Instead, find the first non-label gimple statement in BB and insert before
-      that.  */
-   if (gimple_code (insert_point) == GIMPLE_PHI)
-     {
-       gsi_insert = gsi_after_labels (insert_bb);
-       gsi_move_before (&gsistmt, &gsi_insert);
-     }
-   /* Statements marked for throw can not be in the middle of a basic block. So
-      we can not insert a statement (not marked for throw) immediately after.  */
-   else if (stmt_ends_bb_p (insert_point))
-     {
-       edge succ_edge = find_fallthru_edge (insert_bb->succs);
-       insert_bb = succ_edge->dest;
-       insert_bb_different = (insert_bb != gimple_bb (stmt));
-       /* Insert STMT at the beginning of the successor basic block.  */
-       gsi_insert = gsi_after_labels (insert_bb);
-       gsi_move_before (&gsistmt, &gsi_insert);
-     }
-   else
-     {
-       gsi_insert = gsi_for_stmt (insert_point);
-       gsi_move_after (&gsistmt, &gsi_insert);
-     }
-   /* Set the UID of STMT to that of INSERT_POINT so that subsequent comparisons
-      of UIDs to determine dominance within a basic block works.  */
-   gimple_set_uid (stmt, gimple_uid (insert_point));
-   if (dump_file && (dump_flags & TDF_DETAILS))
-     {
-       fprintf (dump_file, "Moved stmt ");
-       print_gimple_stmt (dump_file, stmt, 0, 0);
-       fprintf (dump_file, " %s to satisfy dependences\n",
-                insert_bb_different ? "to a different BB" : "within same BB");
-     }
- }
- /* If OP is a SSA variable and is not the default definition, return the
-    gimple statement that defines OP. Else return NULL.  */
+ /* If definition of RHS1 or RHS2 dominates STMT, return the later of those
+    two definitions, otherwise return STMT.  */
  
  static inline gimple
get_def_stmt (tree op)
find_insert_point (gimple stmt, tree rhs1, tree rhs2)
  {
-   if (TREE_CODE (op) == SSA_NAME
-       && !SSA_NAME_IS_DEFAULT_DEF (op))
-     return SSA_NAME_DEF_STMT (op);
-   else
-     return NULL;
- }
- /* Ensure that operands in the OPS vector are available for STMT and all
-    gimple statements on which STMT depends.  */
- static void
- ensure_ops_are_available (gimple stmt, vec<operand_entry_t> ops, int opindex)
- {
-   unsigned int len = ops.length ();
-   gimple insert_stmt = stmt;
-   gimple dep_stmts[2];
-   dep_stmts[0] = get_def_stmt (ops[opindex]->op);
-   if (len - opindex == 2)
-     {
-       dep_stmts[1] = get_def_stmt (ops[opindex + 1]->op);
-     }
-   else
-     {
-       gimple stmt1 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
-       ensure_ops_are_available (stmt1, ops, opindex + 1);
-       dep_stmts[1] = stmt1;
-     }
-   for (int i = 0; i < 2; i++)
-     insert_stmt = find_insert_point (insert_stmt, dep_stmts[i]);
-   if (insert_stmt != stmt)
-     insert_stmt_after (stmt, insert_stmt);
+   if (TREE_CODE (rhs1) == SSA_NAME
+       && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs1)))
+     stmt = SSA_NAME_DEF_STMT (rhs1);
+   if (TREE_CODE (rhs2) == SSA_NAME
+       && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs2)))
+     stmt = SSA_NAME_DEF_STMT (rhs2);
+   return stmt;
  }
  
  /* Recursively rewrite our linearized statements so that the operators
     match those in OPS[OPINDEX], putting the computation in rank
-    order.  */
+    order.  Return new lhs.  */
  
- static void
+ static tree
  rewrite_expr_tree (gimple stmt, unsigned int opindex,
-                  vec<operand_entry_t> ops, bool moved)
+                  vec<operand_entry_t> ops, bool changed)
  {
    tree rhs1 = gimple_assign_rhs1 (stmt);
    tree rhs2 = gimple_assign_rhs2 (stmt);
+   tree lhs = gimple_assign_lhs (stmt);
    operand_entry_t oe;
  
    /* The final recursion case for this function is that you have
  
        if (rhs1 != oe1->op || rhs2 != oe2->op)
        {
+         gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+         unsigned int uid = gimple_uid (stmt);
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file, "Transforming ");
              print_gimple_stmt (dump_file, stmt, 0, 0);
            }
  
-         gimple_assign_set_rhs1 (stmt, oe1->op);
-         gimple_assign_set_rhs2 (stmt, oe2->op);
-         update_stmt (stmt);
+         if (changed)
+           {
+             gimple insert_point = find_insert_point (stmt, oe1->op, oe2->op);
+             lhs = make_ssa_name (TREE_TYPE (lhs), NULL);
+             stmt
+               = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt),
+                                               lhs, oe1->op, oe2->op);
+             gimple_set_uid (stmt, uid);
+             gimple_set_visited (stmt, true);
+             if (insert_point == gsi_stmt (gsi))
+               gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+             else
+               insert_stmt_after (stmt, insert_point);
+           }
+         else
+           {
+             gcc_checking_assert (find_insert_point (stmt, oe1->op, oe2->op)
+                                  == stmt);
+             gimple_assign_set_rhs1 (stmt, oe1->op);
+             gimple_assign_set_rhs2 (stmt, oe2->op);
+             update_stmt (stmt);
+           }
          if (rhs1 != oe1->op && rhs1 != oe2->op)
            remove_visited_stmt_chain (rhs1);
  
              print_gimple_stmt (dump_file, stmt, 0, 0);
            }
        }
-       return;
+       return lhs;
      }
  
    /* If we hit here, we should have 3 or more ops left.  */
    /* Rewrite the next operator.  */
    oe = ops[opindex];
  
-   if (oe->op != rhs2)
-     {
-       if (!moved)
-       {
-           ensure_ops_are_available (stmt, ops, opindex);
-         moved = true;
-       }
+   /* Recurse on the LHS of the binary operator, which is guaranteed to
+      be the non-leaf side.  */
+   tree new_rhs1
+     = rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops,
+                        changed || oe->op != rhs2);
  
+   if (oe->op != rhs2 || new_rhs1 != rhs1)
+     {
        if (dump_file && (dump_flags & TDF_DETAILS))
        {
          fprintf (dump_file, "Transforming ");
          print_gimple_stmt (dump_file, stmt, 0, 0);
        }
  
-       gimple_assign_set_rhs2 (stmt, oe->op);
-       update_stmt (stmt);
+       /* If changed is false, this is either opindex == 0
+        or all outer rhs2's were equal to corresponding oe->op,
+        and powi_result is NULL.
+        That means lhs is equivalent before and after reassociation.
+        Otherwise ensure the old lhs SSA_NAME is not reused and
+        create a new stmt as well, so that any debug stmts will be
+        properly adjusted.  */
+       if (changed)
+       {
+         gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+         unsigned int uid = gimple_uid (stmt);
+         gimple insert_point = find_insert_point (stmt, new_rhs1, oe->op);
+         lhs = make_ssa_name (TREE_TYPE (lhs), NULL);
+         stmt = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt),
+                                              lhs, new_rhs1, oe->op);
+         gimple_set_uid (stmt, uid);
+         gimple_set_visited (stmt, true);
+         if (insert_point == gsi_stmt (gsi))
+           gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+         else
+           insert_stmt_after (stmt, insert_point);
+       }
+       else
+       {
+         gcc_checking_assert (find_insert_point (stmt, new_rhs1, oe->op)
+                              == stmt);
+         gimple_assign_set_rhs1 (stmt, new_rhs1);
+         gimple_assign_set_rhs2 (stmt, oe->op);
+         update_stmt (stmt);
+       }
  
        if (dump_file && (dump_flags & TDF_DETAILS))
        {
          print_gimple_stmt (dump_file, stmt, 0, 0);
        }
      }
-   /* Recurse on the LHS of the binary operator, which is guaranteed to
-      be the non-leaf side.  */
-   rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops, moved);
+   return lhs;
  }
  
  /* Find out how many cycles we need to compute statements chain.
@@@ -3260,7 -3309,7 +3309,7 @@@ get_reassociation_width (int ops_num, e
  
  static void
  rewrite_expr_tree_parallel (gimple stmt, int width,
-                           vec<operand_entry_t>  ops)
+                           vec<operand_entry_t> ops)
  {
    enum tree_code opcode = gimple_assign_rhs_code (stmt);
    int op_num = ops.length ();
  static void
  linearize_expr (gimple stmt)
  {
-   gimple_stmt_iterator gsinow, gsirhs;
+   gimple_stmt_iterator gsi;
    gimple binlhs = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
    gimple binrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
+   gimple oldbinrhs = binrhs;
    enum tree_code rhscode = gimple_assign_rhs_code (stmt);
    gimple newbinrhs = NULL;
    struct loop *loop = loop_containing_stmt (stmt);
+   tree lhs = gimple_assign_lhs (stmt);
  
    gcc_assert (is_reassociable_op (binlhs, rhscode, loop)
              && is_reassociable_op (binrhs, rhscode, loop));
  
-   gsinow = gsi_for_stmt (stmt);
-   gsirhs = gsi_for_stmt (binrhs);
-   gsi_move_before (&gsirhs, &gsinow);
-   gimple_set_uid (binrhs, gimple_uid (stmt));
+   gsi = gsi_for_stmt (stmt);
  
    gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
-   gimple_assign_set_rhs1 (binrhs, gimple_assign_lhs (binlhs));
+   binrhs = gimple_build_assign_with_ops (gimple_assign_rhs_code (binrhs),
+                                        make_ssa_name (TREE_TYPE (lhs), NULL),
+                                        gimple_assign_lhs (binlhs),
+                                        gimple_assign_rhs2 (binrhs));
    gimple_assign_set_rhs1 (stmt, gimple_assign_lhs (binrhs));
+   gsi_insert_before (&gsi, binrhs, GSI_SAME_STMT);
+   gimple_set_uid (binrhs, gimple_uid (stmt));
  
    if (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME)
      newbinrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
      }
  
    reassociate_stats.linearized++;
-   update_stmt (binrhs);
-   update_stmt (binlhs);
    update_stmt (stmt);
  
+   gsi = gsi_for_stmt (oldbinrhs);
+   gsi_remove (&gsi, true);
+   release_defs (oldbinrhs);
    gimple_set_visited (stmt, true);
    gimple_set_visited (binlhs, true);
    gimple_set_visited (binrhs, true);
@@@ -3425,10 -3480,12 +3480,12 @@@ get_single_immediate_use (tree lhs
     transform b_3 + b_4 into a_5 = -b_3 + -b_4.  */
  
  static tree
- negate_value (tree tonegate, gimple_stmt_iterator *gsi)
+ negate_value (tree tonegate, gimple_stmt_iterator *gsip)
  {
-   gimple negatedefstmt= NULL;
+   gimple negatedefstmt = NULL;
    tree resultofnegate;
+   gimple_stmt_iterator gsi;
+   unsigned int uid;
  
    /* If we are trying to negate a name, defined by an add, negate the
       add operands instead.  */
        && has_single_use (gimple_assign_lhs (negatedefstmt))
        && gimple_assign_rhs_code (negatedefstmt) == PLUS_EXPR)
      {
-       gimple_stmt_iterator gsi;
        tree rhs1 = gimple_assign_rhs1 (negatedefstmt);
        tree rhs2 = gimple_assign_rhs2 (negatedefstmt);
+       tree lhs = gimple_assign_lhs (negatedefstmt);
+       gimple g;
  
        gsi = gsi_for_stmt (negatedefstmt);
        rhs1 = negate_value (rhs1, &gsi);
-       gimple_assign_set_rhs1 (negatedefstmt, rhs1);
  
        gsi = gsi_for_stmt (negatedefstmt);
        rhs2 = negate_value (rhs2, &gsi);
-       gimple_assign_set_rhs2 (negatedefstmt, rhs2);
  
-       update_stmt (negatedefstmt);
-       return gimple_assign_lhs (negatedefstmt);
+       gsi = gsi_for_stmt (negatedefstmt);
+       lhs = make_ssa_name (TREE_TYPE (lhs), NULL);
+       gimple_set_visited (negatedefstmt, true);
+       g = gimple_build_assign_with_ops (PLUS_EXPR, lhs, rhs1, rhs2);
+       gimple_set_uid (g, gimple_uid (negatedefstmt));
+       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+       return lhs;
      }
  
    tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate);
-   resultofnegate = force_gimple_operand_gsi (gsi, tonegate, true,
+   resultofnegate = force_gimple_operand_gsi (gsip, tonegate, true,
                                             NULL_TREE, true, GSI_SAME_STMT);
+   gsi = *gsip;
+   uid = gimple_uid (gsi_stmt (gsi));
+   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+     {
+       gimple stmt = gsi_stmt (gsi);
+       if (gimple_uid (stmt) != 0)
+       break;
+       gimple_set_uid (stmt, uid);
+     }
    return resultofnegate;
  }
  
@@@ -3552,7 -3622,8 +3622,7 @@@ acceptable_pow_call (gimple stmt, tree 
        return false;
  
        *exponent = real_to_integer (&c);
 -      real_from_integer (&cint, VOIDmode, *exponent,
 -                       *exponent < 0 ? -1 : 0, 0);
 +      real_from_integer (&cint, VOIDmode, *exponent, SIGNED);
        if (!real_identical (&c, &cint))
        return false;
  
        *base = gimple_call_arg (stmt, 0);
        arg1 = gimple_call_arg (stmt, 1);
  
 -      if (!host_integerp (arg1, 0))
 +      if (!tree_fits_shwi_p (arg1))
        return false;
  
 -      *exponent = TREE_INT_CST_LOW (arg1);
 +      *exponent = tree_to_shwi (arg1);
        break;
  
      default:
@@@ -3763,16 -3834,18 +3833,18 @@@ repropagate_negates (void
                 plus_negates vector.  */
              gimple feed = SSA_NAME_DEF_STMT (negate);
              tree a = gimple_assign_rhs1 (feed);
-             tree rhs2 = gimple_assign_rhs2 (user);
-             gimple_stmt_iterator gsi = gsi_for_stmt (feed), gsi2;
-             gimple_replace_ssa_lhs (feed, negate);
-             gimple_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, a, rhs2);
-             update_stmt (gsi_stmt (gsi));
-             gsi2 = gsi_for_stmt (user);
-             gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, negate, NULL);
-             update_stmt (gsi_stmt (gsi2));
-             gsi_move_before (&gsi, &gsi2);
-             plus_negates.safe_push (gimple_assign_lhs (gsi_stmt (gsi2)));
+             tree b = gimple_assign_rhs2 (user);
+             gimple_stmt_iterator gsi = gsi_for_stmt (feed);
+             gimple_stmt_iterator gsi2 = gsi_for_stmt (user);
+             tree x = make_ssa_name (TREE_TYPE (gimple_assign_lhs (feed)), NULL);
+             gimple g = gimple_build_assign_with_ops (PLUS_EXPR, x, a, b);
+             gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
+             gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, x, NULL);
+             user = gsi_stmt (gsi2);
+             update_stmt (user);
+             gsi_remove (&gsi, true);
+             release_defs (feed);
+             plus_negates.safe_push (gimple_assign_lhs (user));
            }
          else
            {
@@@ -3819,18 -3892,21 +3891,21 @@@ can_reassociate_p (tree op
     we want to break up k = t - q, but we won't until we've transformed q
     = b - r, which won't be broken up until we transform b = c - d.
  
-    En passant, clear the GIMPLE visited flag on every statement.  */
+    En passant, clear the GIMPLE visited flag on every statement
+    and set UIDs within each basic block.  */
  
  static void
  break_up_subtract_bb (basic_block bb)
  {
    gimple_stmt_iterator gsi;
    basic_block son;
+   unsigned int uid = 1;
  
    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
      {
        gimple stmt = gsi_stmt (gsi);
        gimple_set_visited (stmt, false);
+       gimple_set_uid (stmt, uid++);
  
        if (!is_gimple_assign (stmt)
          || !can_reassociate_p (gimple_assign_lhs (stmt)))
@@@ -4366,6 -4442,7 +4441,7 @@@ reassociate_bb (basic_block bb
                  enum machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
                  int ops_num = ops.length ();
                  int width = get_reassociation_width (ops_num, rhs_code, mode);
+                 tree new_lhs = lhs;
  
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    fprintf (dump_file,
                        if (len >= 3)
                          swap_ops_for_binary_stmt (ops, len - 3, stmt);
  
-                     rewrite_expr_tree (stmt, 0, ops, false);
+                     new_lhs = rewrite_expr_tree (stmt, 0, ops,
+                                                  powi_result != NULL);
                      }
  
                  /* If we combined some repeated factors into a 
                     reassociated operands.  */
                  if (powi_result)
                    {
-                     gimple mul_stmt;
-                     tree type = TREE_TYPE (gimple_get_lhs (stmt));
+                     gimple mul_stmt, lhs_stmt = SSA_NAME_DEF_STMT (lhs);
+                     tree type = TREE_TYPE (lhs);
                      tree target_ssa = make_temp_ssa_name (type, NULL,
                                                            "reassocpow");
-                     gimple_set_lhs (stmt, target_ssa);
-                     update_stmt (stmt);
+                     gimple_set_lhs (lhs_stmt, target_ssa);
+                     update_stmt (lhs_stmt);
+                     if (lhs != new_lhs)
+                       target_ssa = new_lhs;
                      mul_stmt = gimple_build_assign_with_ops (MULT_EXPR, lhs,
                                                               powi_result,
                                                               target_ssa);
@@@ -4445,7 -4525,6 +4524,6 @@@ static voi
  do_reassoc (void)
  {
    break_up_subtract_bb (ENTRY_BLOCK_PTR);
-   renumber_gimple_stmt_uids ();
    reassociate_bb (EXIT_BLOCK_PTR);
  }
  
diff --combined gcc/tree-ssa-sccvn.c
index a56c55b622f2ef20c4d2d38bc03e7e0a894b41a8,ed4e1db718c6f6553a735f4e376a35c4ae694052..5d7bcfc9ab6d99a98755cfc0271e21b7821eb339
@@@ -26,13 -26,17 +26,17 @@@ along with GCC; see the file COPYING3
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
  #include "tree-inline.h"
- #include "tree-ssa.h"
  #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
+ #include "tree-ssa.h"
  #include "dumpfile.h"
  #include "hash-table.h"
  #include "alloc-pool.h"
  #include "flags.h"
- #include "bitmap.h"
  #include "cfgloop.h"
  #include "params.h"
  #include "tree-ssa-propagate.h"
@@@ -653,11 -657,11 +657,11 @@@ vn_reference_eq (const_vn_reference_t c
      }
    else if (INTEGRAL_TYPE_P (vr1->type)
           && (TYPE_PRECISION (vr1->type)
 -             != TREE_INT_CST_LOW (TYPE_SIZE (vr1->type))))
 +             != tree_to_hwi (TYPE_SIZE (vr1->type))))
      return false;
    else if (INTEGRAL_TYPE_P (vr2->type)
           && (TYPE_PRECISION (vr2->type)
 -             != TREE_INT_CST_LOW (TYPE_SIZE (vr2->type))))
 +             != tree_to_hwi (TYPE_SIZE (vr2->type))))
      return false;
  
    i = 0;
@@@ -777,8 -781,8 +781,8 @@@ copy_reference_ops_from_ref (tree ref, 
        case MEM_REF:
          /* The base address gets its own vn_reference_op_s structure.  */
          temp.op0 = TREE_OPERAND (ref, 1);
 -        if (host_integerp (TREE_OPERAND (ref, 1), 0))
 -          temp.off = TREE_INT_CST_LOW (TREE_OPERAND (ref, 1));
 +        if (tree_fits_shwi_p (TREE_OPERAND (ref, 1)))
 +          temp.off = tree_to_shwi (TREE_OPERAND (ref, 1));
          break;
        case BIT_FIELD_REF:
          /* Record bits and position.  */
                && TREE_CODE (this_offset) == INTEGER_CST)
              {
                tree bit_offset = DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1));
 -              if (TREE_INT_CST_LOW (bit_offset) % BITS_PER_UNIT == 0)
 +              if (tree_to_hwi (bit_offset) % BITS_PER_UNIT == 0)
                  {
 -                  double_int off
 -                    = tree_to_double_int (this_offset)
 -                      + tree_to_double_int (bit_offset)
 -                      .rshift (BITS_PER_UNIT == 8
 -                                 ? 3 : exact_log2 (BITS_PER_UNIT));
 -                  if (off.fits_shwi ())
 -                    temp.off = off.low;
 +                  offset_int off
 +                    = (wi::to_offset (this_offset)
 +                       + wi::lrshift (wi::to_offset (bit_offset),
 +                                      BITS_PER_UNIT == 8
 +                                      ? 3 : exact_log2 (BITS_PER_UNIT)));
 +                  if (wi::fits_shwi_p (off))
 +                    temp.off = off.to_shwi ();
                  }
              }
          }
              && TREE_CODE (temp.op1) == INTEGER_CST
              && TREE_CODE (temp.op2) == INTEGER_CST)
            {
 -            double_int off = tree_to_double_int (temp.op0);
 -            off += -tree_to_double_int (temp.op1);
 -            off *= tree_to_double_int (temp.op2);
 -            if (off.fits_shwi ())
 -              temp.off = off.low;
 +            offset_int off = ((wi::to_offset (temp.op0)
 +                               - wi::to_offset (temp.op1))
 +                              * wi::to_offset (temp.op2));
 +            if (wi::fits_shwi_p (off))
 +              temp.off = off.to_shwi();
            }
          break;
        case VAR_DECL:
          break;
        case IMAGPART_EXPR:
          /* This is only interesting for its constant offset.  */
 -        temp.off = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (ref)));
 +        temp.off = tree_to_hwi (TYPE_SIZE_UNIT (TREE_TYPE (ref)));
          break;
        default:
          gcc_unreachable ();
@@@ -931,10 -935,10 +935,10 @@@ ao_ref_init_from_vn_reference (ao_ref *
      }
    if (size_tree != NULL_TREE)
      {
 -      if (!host_integerp (size_tree, 1))
 +      if (!tree_fits_uhwi_p (size_tree))
        size = -1;
        else
 -      size = TREE_INT_CST_LOW (size_tree);
 +      size = tree_to_uhwi (size_tree);
      }
  
    /* Initially, maxsize is the same as the accessed element size.
  
        /* And now the usual component-reference style ops.  */
        case BIT_FIELD_REF:
 -        offset += tree_low_cst (op->op1, 0);
 +        offset += tree_to_shwi (op->op1);
          break;
  
        case COMPONENT_REF:
               parts manually.  */
  
            if (op->op1
 -              || !host_integerp (DECL_FIELD_OFFSET (field), 1))
 +              || !tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)))
              max_size = -1;
            else
              {
 -              offset += (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
 +              offset += (tree_to_uhwi (DECL_FIELD_OFFSET (field))
                           * BITS_PER_UNIT);
 -              offset += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
 +              offset += tree_to_hwi (DECL_FIELD_BIT_OFFSET (field));
              }
            break;
          }
        case ARRAY_RANGE_REF:
        case ARRAY_REF:
          /* We recorded the lower bound and the element size.  */
 -        if (!host_integerp (op->op0, 0)
 -            || !host_integerp (op->op1, 0)
 -            || !host_integerp (op->op2, 0))
 +        if (!tree_fits_shwi_p (op->op0)
 +            || !tree_fits_shwi_p (op->op1)
 +            || !tree_fits_shwi_p (op->op2))
            max_size = -1;
          else
            {
 -            HOST_WIDE_INT hindex = TREE_INT_CST_LOW (op->op0);
 -            hindex -= TREE_INT_CST_LOW (op->op1);
 -            hindex *= TREE_INT_CST_LOW (op->op2);
 +            HOST_WIDE_INT hindex = tree_to_shwi (op->op0);
 +            hindex -= tree_to_shwi (op->op1);
 +            hindex *= tree_to_shwi (op->op2);
              hindex *= BITS_PER_UNIT;
              offset += hindex;
            }
@@@ -1146,12 -1150,13 +1150,12 @@@ vn_reference_fold_indirect (vec<vn_refe
    gcc_checking_assert (addr_base && TREE_CODE (addr_base) != MEM_REF);
    if (addr_base != TREE_OPERAND (op->op0, 0))
      {
 -      double_int off = tree_to_double_int (mem_op->op0);
 -      off = off.sext (TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
 -      off += double_int::from_shwi (addr_offset);
 -      mem_op->op0 = double_int_to_tree (TREE_TYPE (mem_op->op0), off);
 +      offset_int off = offset_int::from (mem_op->op0, SIGNED);
 +      off += addr_offset;
 +      mem_op->op0 = wide_int_to_tree (TREE_TYPE (mem_op->op0), off);
        op->op0 = build_fold_addr_expr (addr_base);
 -      if (host_integerp (mem_op->op0, 0))
 -      mem_op->off = TREE_INT_CST_LOW (mem_op->op0);
 +      if (tree_fits_shwi_p (mem_op->op0))
 +      mem_op->off = tree_to_shwi (mem_op->op0);
        else
        mem_op->off = -1;
      }
@@@ -1168,7 -1173,7 +1172,7 @@@ vn_reference_maybe_forwprop_address (ve
    vn_reference_op_t mem_op = &(*ops)[i - 1];
    gimple def_stmt;
    enum tree_code code;
 -  double_int off;
 +  offset_int off;
  
    def_stmt = SSA_NAME_DEF_STMT (op->op0);
    if (!is_gimple_assign (def_stmt))
        && code != POINTER_PLUS_EXPR)
      return;
  
 -  off = tree_to_double_int (mem_op->op0);
 -  off = off.sext (TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
 +  off = offset_int::from (mem_op->op0, SIGNED);
  
    /* The only thing we have to do is from &OBJ.foo.bar add the offset
       from .foo.bar to the preceding MEM_REF offset and replace the
          || TREE_CODE (addr_base) != MEM_REF)
        return;
  
 -      off += double_int::from_shwi (addr_offset);
 +      off += addr_offset;
        off += mem_ref_offset (addr_base);
        op->op0 = TREE_OPERAND (addr_base, 0);
      }
          || TREE_CODE (ptroff) != INTEGER_CST)
        return;
  
 -      off += tree_to_double_int (ptroff);
 +      off += wi::to_offset (ptroff);
        op->op0 = ptr;
      }
  
 -  mem_op->op0 = double_int_to_tree (TREE_TYPE (mem_op->op0), off);
 -  if (host_integerp (mem_op->op0, 0))
 -    mem_op->off = TREE_INT_CST_LOW (mem_op->op0);
 +  mem_op->op0 = wide_int_to_tree (TREE_TYPE (mem_op->op0), off);
 +  if (tree_fits_shwi_p (mem_op->op0))
 +    mem_op->off = tree_to_shwi (mem_op->op0);
    else
      mem_op->off = -1;
    if (TREE_CODE (op->op0) == SSA_NAME)
@@@ -1295,7 -1301,7 +1299,7 @@@ fully_constant_vn_reference_p (vn_refer
          && compare_tree_int (op->op0, TREE_STRING_LENGTH (arg0->op0)) < 0)
        return build_int_cst_type (op->type,
                                   (TREE_STRING_POINTER (arg0->op0)
 -                                  [TREE_INT_CST_LOW (op->op0)]));
 +                                  [tree_to_hwi (op->op0)]));
      }
  
    return NULL_TREE;
@@@ -1367,11 -1373,11 +1371,11 @@@ valueize_refs_1 (vec<vn_reference_op_s
               && TREE_CODE (vro->op1) == INTEGER_CST
               && TREE_CODE (vro->op2) == INTEGER_CST)
        {
 -        double_int off = tree_to_double_int (vro->op0);
 -        off += -tree_to_double_int (vro->op1);
 -        off *= tree_to_double_int (vro->op2);
 -        if (off.fits_shwi ())
 -          vro->off = off.low;
 +        offset_int off = ((wi::to_offset (vro->op0)
 +                           - wi::to_offset (vro->op1))
 +                          * wi::to_offset (vro->op2));
 +        if (wi::fits_shwi_p (off))
 +          vro->off = off.to_shwi ();
        }
      }
  
@@@ -1579,16 -1585,16 +1583,16 @@@ vn_reference_lookup_3 (ao_ref *ref, tre
    if (is_gimple_reg_type (vr->type)
        && gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET)
        && integer_zerop (gimple_call_arg (def_stmt, 1))
 -      && host_integerp (gimple_call_arg (def_stmt, 2), 1)
 +      && tree_fits_uhwi_p (gimple_call_arg (def_stmt, 2))
        && TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR)
      {
        tree ref2 = TREE_OPERAND (gimple_call_arg (def_stmt, 0), 0);
        tree base2;
        HOST_WIDE_INT offset2, size2, maxsize2;
        base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &maxsize2);
 -      size2 = TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2)) * 8;
 +      size2 = tree_to_uhwi (gimple_call_arg (def_stmt, 2)) * 8;
        if ((unsigned HOST_WIDE_INT)size2 / 8
 -        == TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2))
 +        == tree_to_uhwi (gimple_call_arg (def_stmt, 2))
          && maxsize2 != -1
          && operand_equal_p (base, base2, 0)
          && offset2 <= offset
            {
              tree val = NULL_TREE;
              HOST_WIDE_INT elsz
 -              = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (TREE_TYPE (rhs1))));
 +              = tree_to_hwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (rhs1))));
              if (gimple_assign_rhs_code (def_stmt2) == COMPLEX_EXPR)
                {
                  if (off == 0)
               || TREE_CODE (gimple_call_arg (def_stmt, 0)) == SSA_NAME)
           && (TREE_CODE (gimple_call_arg (def_stmt, 1)) == ADDR_EXPR
               || TREE_CODE (gimple_call_arg (def_stmt, 1)) == SSA_NAME)
 -         && host_integerp (gimple_call_arg (def_stmt, 2), 1))
 +         && tree_fits_uhwi_p (gimple_call_arg (def_stmt, 2)))
      {
        tree lhs, rhs;
        ao_ref r;
          if (!tem)
            return (void *)-1;
          if (TREE_CODE (tem) == MEM_REF
 -            && host_integerp (TREE_OPERAND (tem, 1), 1))
 +            && tree_fits_uhwi_p (TREE_OPERAND (tem, 1)))
            {
              lhs = TREE_OPERAND (tem, 0);
 -            lhs_offset += TREE_INT_CST_LOW (TREE_OPERAND (tem, 1));
 +            lhs_offset += tree_to_uhwi (TREE_OPERAND (tem, 1));
            }
          else if (DECL_P (tem))
            lhs = build_fold_addr_expr (tem);
          if (!tem)
            return (void *)-1;
          if (TREE_CODE (tem) == MEM_REF
 -            && host_integerp (TREE_OPERAND (tem, 1), 1))
 +            && tree_fits_uhwi_p (TREE_OPERAND (tem, 1)))
            {
              rhs = TREE_OPERAND (tem, 0);
 -            rhs_offset += TREE_INT_CST_LOW (TREE_OPERAND (tem, 1));
 +            rhs_offset += tree_to_uhwi (TREE_OPERAND (tem, 1));
            }
          else if (DECL_P (tem))
            rhs = build_fold_addr_expr (tem);
          && TREE_CODE (rhs) != ADDR_EXPR)
        return (void *)-1;
  
 -      copy_size = TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2));
 +      copy_size = tree_to_hwi (gimple_call_arg (def_stmt, 2));
  
        /* The bases of the destination and the references have to agree.  */
        if ((TREE_CODE (base) != MEM_REF
           && !DECL_P (base))
          || (TREE_CODE (base) == MEM_REF
              && (TREE_OPERAND (base, 0) != lhs
 -                || !host_integerp (TREE_OPERAND (base, 1), 1)))
 +                || !tree_fits_uhwi_p (TREE_OPERAND (base, 1))))
          || (DECL_P (base)
              && (TREE_CODE (lhs) != ADDR_EXPR
                  || TREE_OPERAND (lhs, 0) != base)))
        /* And the access has to be contained within the memcpy destination.  */
        at = offset / BITS_PER_UNIT;
        if (TREE_CODE (base) == MEM_REF)
 -      at += TREE_INT_CST_LOW (TREE_OPERAND (base, 1));
 +      at += tree_to_hwi (TREE_OPERAND (base, 1));
        if (lhs_offset > at
          || lhs_offset + copy_size < at + maxsize / BITS_PER_UNIT)
        return (void *)-1;
@@@ -3214,12 -3220,12 +3218,12 @@@ simplify_binary_expression (gimple stmt
    /* Pointer plus constant can be represented as invariant address.
       Do so to allow further propatation, see also tree forwprop.  */
    if (code == POINTER_PLUS_EXPR
 -      && host_integerp (op1, 1)
 +      && tree_fits_uhwi_p (op1)
        && TREE_CODE (op0) == ADDR_EXPR
        && is_gimple_min_invariant (op0))
      return build_invariant_address (TREE_TYPE (op0),
                                    TREE_OPERAND (op0, 0),
 -                                  TREE_INT_CST_LOW (op1));
 +                                  tree_to_uhwi (op1));
  
    /* Avoid folding if nothing changed.  */
    if (op0 == gimple_assign_rhs1 (stmt)
diff --combined gcc/tree-ssa-strlen.c
index d2899539ca512f8bb9b818806967ef08343026c3,ea73179eea88030aef25c6bb6fc3282f1a0c04bd..4d3acf303da5e2d6fdb03e1ae94998c2c840025a
@@@ -21,8 -21,15 +21,15 @@@ along with GCC; see the file COPYING3
  #include "config.h"
  #include "system.h"
  #include "coretypes.h"
+ #include "tree.h"
  #include "hash-table.h"
- #include "tree-ssa.h"
+ #include "bitmap.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "tree-pass.h"
  #include "domwalk.h"
  #include "alloc-pool.h"
@@@ -205,10 -212,10 +212,10 @@@ get_stridx (tree exp
  
    s = string_constant (exp, &o);
    if (s != NULL_TREE
 -      && (o == NULL_TREE || host_integerp (o, 0))
 +      && (o == NULL_TREE || tree_fits_shwi_p (o))
        && TREE_STRING_LENGTH (s) > 0)
      {
 -      HOST_WIDE_INT offset = o ? tree_low_cst (o, 0) : 0;
 +      HOST_WIDE_INT offset = o ? tree_to_shwi (o) : 0;
        const char *p = TREE_STRING_POINTER (s);
        int max = TREE_STRING_LENGTH (s) - 1;
  
@@@ -836,16 -843,16 +843,16 @@@ adjust_last_stmt (strinfo si, gimple st
      }
  
    len = gimple_call_arg (last.stmt, 2);
 -  if (host_integerp (len, 1))
 +  if (tree_fits_uhwi_p (len))
      {
 -      if (!host_integerp (last.len, 1)
 +      if (!tree_fits_uhwi_p (last.len)
          || integer_zerop (len)
 -        || (unsigned HOST_WIDE_INT) tree_low_cst (len, 1)
 -           != (unsigned HOST_WIDE_INT) tree_low_cst (last.len, 1) + 1)
 +        || (unsigned HOST_WIDE_INT) tree_to_uhwi (len)
 +           != (unsigned HOST_WIDE_INT) tree_to_uhwi (last.len) + 1)
        return;
        /* Don't adjust the length if it is divisible by 4, it is more efficient
         to store the extra '\0' in that case.  */
 -      if ((((unsigned HOST_WIDE_INT) tree_low_cst (len, 1)) & 3) == 0)
 +      if ((((unsigned HOST_WIDE_INT) tree_to_uhwi (len)) & 3) == 0)
        return;
      }
    else if (TREE_CODE (len) == SSA_NAME)
@@@ -1300,7 -1307,7 +1307,7 @@@ handle_builtin_memcpy (enum built_in_fu
      return;
  
    if (olddsi != NULL
 -      && host_integerp (len, 1)
 +      && tree_fits_uhwi_p (len)
        && !integer_zerop (len))
      adjust_last_stmt (olddsi, stmt, false);
  
        si = NULL;
        /* Handle memcpy (x, "abcd", 5) or
         memcpy (x, "abc\0uvw", 7).  */
 -      if (!host_integerp (len, 1)
 -        || (unsigned HOST_WIDE_INT) tree_low_cst (len, 1)
 +      if (!tree_fits_uhwi_p (len)
 +        || (unsigned HOST_WIDE_INT) tree_to_uhwi (len)
             <= (unsigned HOST_WIDE_INT) ~idx)
        return;
      }
@@@ -1616,11 -1623,11 +1623,11 @@@ handle_pointer_plus (gimple_stmt_iterat
    if (idx < 0)
      {
        tree off = gimple_assign_rhs2 (stmt);
 -      if (host_integerp (off, 1)
 -        && (unsigned HOST_WIDE_INT) tree_low_cst (off, 1)
 +      if (tree_fits_uhwi_p (off)
 +        && (unsigned HOST_WIDE_INT) tree_to_uhwi (off)
             <= (unsigned HOST_WIDE_INT) ~idx)
        ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
 -          = ~(~idx - (int) tree_low_cst (off, 1));
 +          = ~(~idx - (int) tree_to_uhwi (off));
        return;
      }
  
index affc0b69dcc2b16137493ab755948c9d9472542a,6f3a4cee29f2fcd7101c1afb5debefdc93aea002..78d1a7c2e537d106685faede7eefaa066d54d967
  #include "flags.h"
  #include "basic-block.h"
  #include "tree.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-ssanames.h"
+ #include "tree-into-ssa.h"
+ #include "tree-dfa.h"
  #include "tree-inline.h"
  #include "diagnostic-core.h"
- #include "gimple.h"
  #include "hash-table.h"
  #include "function.h"
- #include "cgraph.h"
  #include "tree-pass.h"
  #include "alloc-pool.h"
  #include "splay-tree.h"
  #include "params.h"
- #include "cgraph.h"
  #include "alias.h"
  #include "pointer-set.h"
  
@@@ -2875,10 -2877,10 +2877,10 @@@ get_constraint_for_ssa_var (tree t, vec
        && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
      {
        struct varpool_node *node = varpool_get_node (t);
-       if (node && node->symbol.alias && node->symbol.analyzed)
+       if (node && node->alias && node->analyzed)
        {
          node = varpool_variable_node (node, NULL);
-         t = node->symbol.decl;
+         t = node->decl;
        }
      }
  
@@@ -2974,12 -2976,12 +2976,12 @@@ process_constraint (constraint_t t
  static HOST_WIDE_INT
  bitpos_of_field (const tree fdecl)
  {
 -  if (!host_integerp (DECL_FIELD_OFFSET (fdecl), 0)
 -      || !host_integerp (DECL_FIELD_BIT_OFFSET (fdecl), 0))
 +  if (!tree_fits_shwi_p (DECL_FIELD_OFFSET (fdecl))
 +      || !tree_fits_shwi_p (DECL_FIELD_BIT_OFFSET (fdecl)))
      return -1;
  
 -  return (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (fdecl)) * BITS_PER_UNIT
 -        + TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fdecl)));
 +  return (tree_to_shwi (DECL_FIELD_OFFSET (fdecl)) * BITS_PER_UNIT
 +        + tree_to_shwi (DECL_FIELD_BIT_OFFSET (fdecl)));
  }
  
  
@@@ -3012,13 -3014,14 +3014,13 @@@ get_constraint_for_ptr_offset (tree ptr
    else
      {
        /* Sign-extend the offset.  */
 -      double_int soffset = tree_to_double_int (offset)
 -                         .sext (TYPE_PRECISION (TREE_TYPE (offset)));
 -      if (!soffset.fits_shwi ())
 +      offset_int soffset = offset_int::from (offset, SIGNED);
 +      if (!wi::fits_shwi_p (soffset))
        rhsoffset = UNKNOWN_OFFSET;
        else
        {
          /* Make sure the bit-offset also fits.  */
 -        HOST_WIDE_INT rhsunitoffset = soffset.low;
 +        HOST_WIDE_INT rhsunitoffset = soffset.to_shwi ();
          rhsoffset = rhsunitoffset * BITS_PER_UNIT;
          if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
            rhsoffset = UNKNOWN_OFFSET;
@@@ -3408,8 -3411,8 +3410,8 @@@ get_constraint_for_1 (tree t, vec<ce_s
                  && curr)
                {
                  unsigned HOST_WIDE_INT size;
 -                if (host_integerp (TYPE_SIZE (TREE_TYPE (t)), 1))
 -                  size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (t)));
 +                if (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (t))))
 +                  size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (t)));
                  else
                    size = -1;
                  for (; curr; curr = vi_next (curr))
@@@ -5327,7 -5330,7 +5329,7 @@@ push_fields_onto_fieldstack (tree type
              }
  
            if (!DECL_SIZE (field)
 -              || !host_integerp (DECL_SIZE (field), 1))
 +              || !tree_fits_uhwi_p (DECL_SIZE (field)))
              has_unknown_size = true;
  
            /* If adjacent fields do not contain pointers merge them.  */
                && !pair->has_unknown_size
                && pair->offset + (HOST_WIDE_INT)pair->size == offset + foff)
              {
 -              pair->size += TREE_INT_CST_LOW (DECL_SIZE (field));
 +              pair->size += tree_to_hwi (DECL_SIZE (field));
              }
            else
              {
                e.offset = offset + foff;
                e.has_unknown_size = has_unknown_size;
                if (!has_unknown_size)
 -                e.size = TREE_INT_CST_LOW (DECL_SIZE (field));
 +                e.size = tree_to_hwi (DECL_SIZE (field));
                else
                  e.size = -1;
                e.must_have_pointers = must_have_pointers_p;
@@@ -5603,7 -5606,7 +5605,7 @@@ create_variable_info_for_1 (tree decl, 
    unsigned int i;
  
    if (!declsize
 -      || !host_integerp (declsize, 1))
 +      || !tree_fits_uhwi_p (declsize))
      {
        vi = new_var_info (decl, name);
        vi->offset = 0;
        vi = new_var_info (decl, name);
        vi->offset = 0;
        vi->may_have_pointers = true;
 -      vi->fullsize = TREE_INT_CST_LOW (declsize);
 +      vi->fullsize = tree_to_hwi (declsize);
        vi->size = vi->fullsize;
        vi->is_full_var = true;
        fieldstack.release ();
      }
  
    vi = new_var_info (decl, name);
 -  vi->fullsize = TREE_INT_CST_LOW (declsize);
 +  vi->fullsize = tree_to_hwi (declsize);
    for (i = 0, newvi = vi;
         fieldstack.iterate (i, &fo);
         ++i, newvi = vi_next (newvi))
@@@ -5751,7 -5754,7 +5753,7 @@@ create_variable_info_for (tree decl, co
          /* If this is a global variable with an initializer and we are in
             IPA mode generate constraints for it.  */
          if (DECL_INITIAL (decl)
-             && vnode->symbol.definition)
+             && vnode->definition)
            {
              vec<ce_s> rhsc = vNULL;
              struct constraint_expr lhs, *rhsp;
@@@ -7057,9 -7060,9 +7059,9 @@@ struct pt_solution ipa_escaped_p
  static bool
  associate_varinfo_to_alias (struct cgraph_node *node, void *data)
  {
-   if ((node->symbol.alias || node->thunk.thunk_p)
-       && node->symbol.analyzed)
-     insert_vi_for_tree (node->symbol.decl, (varinfo_t)data);
+   if ((node->alias || node->thunk.thunk_p)
+       && node->analyzed)
+     insert_vi_for_tree (node->decl, (varinfo_t)data);
    return false;
  }
  
@@@ -7094,18 -7097,18 +7096,18 @@@ ipa_pta_execute (void
  
        gcc_assert (!node->clone_of);
  
-       vi = create_function_info_for (node->symbol.decl,
-                                    alias_get_name (node->symbol.decl));
+       vi = create_function_info_for (node->decl,
+                                    alias_get_name (node->decl));
        cgraph_for_node_and_aliases (node, associate_varinfo_to_alias, vi, true);
      }
  
    /* Create constraints for global variables and their initializers.  */
    FOR_EACH_VARIABLE (var)
      {
-       if (var->symbol.alias && var->symbol.analyzed)
+       if (var->alias && var->analyzed)
        continue;
  
-       get_vi_for_tree (var->symbol.decl);
+       get_vi_for_tree (var->decl);
      }
  
    if (dump_file)
        {
          fprintf (dump_file,
                   "Generating constraints for %s", cgraph_node_name (node));
-         if (DECL_ASSEMBLER_NAME_SET_P (node->symbol.decl))
+         if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
            fprintf (dump_file, " (%s)",
                     IDENTIFIER_POINTER
-                      (DECL_ASSEMBLER_NAME (node->symbol.decl)));
+                      (DECL_ASSEMBLER_NAME (node->decl)));
          fprintf (dump_file, "\n");
        }
  
-       func = DECL_STRUCT_FUNCTION (node->symbol.decl);
+       func = DECL_STRUCT_FUNCTION (node->decl);
        push_cfun (func);
  
        /* For externally visible or attribute used annotated functions use
         local constraints for their arguments.
         For local functions we see all callers and thus do not need initial
         constraints for parameters.  */
-       if (node->symbol.used_from_other_partition
-         || node->symbol.externally_visible
-         || node->symbol.force_output)
+       if (node->used_from_other_partition
+         || node->externally_visible
+         || node->force_output)
        {
          intra_create_variable_infos ();
  
          /* We also need to make function return values escape.  Nothing
             escapes by returning from main though.  */
-         if (!MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
+         if (!MAIN_NAME_P (DECL_NAME (node->decl)))
            {
              varinfo_t fi, rvi;
-             fi = lookup_vi_for_tree (node->symbol.decl);
+             fi = lookup_vi_for_tree (node->decl);
              rvi = first_vi_for_offset (fi, fi_result);
              if (rvi && rvi->offset == fi_result)
                {
        if (!cgraph_function_with_gimple_body_p (node) || node->clone_of)
        continue;
  
-       fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
+       fn = DECL_STRUCT_FUNCTION (node->decl);
  
        /* Compute the points-to sets for pointer SSA_NAMEs.  */
        FOR_EACH_VEC_ELT (*fn->gimple_df->ssa_names, i, ptr)
        }
  
        /* Compute the call-use and call-clobber sets for all direct calls.  */
-       fi = lookup_vi_for_tree (node->symbol.decl);
+       fi = lookup_vi_for_tree (node->decl);
        gcc_assert (fi->is_fn_info);
        clobbers
        = find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers));
diff --combined gcc/tree-ssa-uninit.c
index 43ca5268c582dbb6f0eb3e3086d58c419d3ab9ce,5e376a1df51407661d27becb0cbaf5f7d045d51c..108da393234f7c657512839ad4666a2432dabaff
@@@ -30,8 -30,11 +30,11 @@@ along with GCC; see the file COPYING3
  #include "gimple-pretty-print.h"
  #include "bitmap.h"
  #include "pointer-set.h"
- #include "tree-ssa.h"
  #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssa.h"
  #include "tree-inline.h"
  #include "hashtab.h"
  #include "tree-pass.h"
@@@ -848,11 -851,12 +851,11 @@@ is_value_included_in (tree val, tree bo
        if (cmpc == EQ_EXPR)
          result = tree_int_cst_equal (val, boundary);
        else if (cmpc == LT_EXPR)
 -        result = INT_CST_LT_UNSIGNED (val, boundary);
 +        result = INT_CST_LT (val, boundary);
        else
          {
            gcc_assert (cmpc == LE_EXPR);
 -          result = (tree_int_cst_equal (val, boundary)
 -                    || INT_CST_LT_UNSIGNED (val, boundary));
 +          result = INT_CST_LE (val, boundary);
          }
      }
    else
diff --combined gcc/tree-ssa.c
index 8706f95f5d0a1ef3be6ebe44c6eb3f4c0737a20a,0b743d1d435528a19fadeee68dca747465374328..9072ce11673921409ae16cf91f79c1010af5c65a
@@@ -30,10 -30,15 +30,15 @@@ along with GCC; see the file COPYING3
  #include "basic-block.h"
  #include "function.h"
  #include "gimple-pretty-print.h"
- #include "bitmap.h"
  #include "pointer-set.h"
- #include "tree-ssa.h"
  #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-into-ssa.h"
+ #include "tree-ssa.h"
  #include "tree-inline.h"
  #include "hashtab.h"
  #include "tree-pass.h"
@@@ -1421,9 -1426,9 +1426,9 @@@ non_rewritable_mem_ref_base (tree ref
           || TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE)
          && useless_type_conversion_p (TREE_TYPE (base),
                                        TREE_TYPE (TREE_TYPE (decl)))
 -        && mem_ref_offset (base).fits_uhwi ()
 -        && tree_to_double_int (TYPE_SIZE_UNIT (TREE_TYPE (decl)))
 -           .ugt (mem_ref_offset (base))
 +        && wi::fits_uhwi_p (mem_ref_offset (base))
 +        && wi::gtu_p (wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))),
 +                      mem_ref_offset (base))
          && multiple_of_p (sizetype, TREE_OPERAND (base, 1),
                            TYPE_SIZE_UNIT (TREE_TYPE (base))))
        return NULL_TREE;
diff --combined gcc/tree-ssanames.c
index b1ef37d687918a6626ba2e25a2ecddf675f9861f,763589125695ce9f4402e58aa41162e9c3d08f97..2c177eeaec8affbffde0db9a5be13d2a12b0170a
@@@ -22,6 -22,12 +22,12 @@@ along with GCC; see the file COPYING3
  #include "coretypes.h"
  #include "tm.h"
  #include "tree.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-into-ssa.h"
  #include "tree-ssa.h"
  #include "tree-pass.h"
  
@@@ -173,7 -179,7 +179,7 @@@ make_ssa_name_fn (struct function *fn, 
  /* Store range information MIN, and MAX to tree ssa_name NAME.  */
  
  void
 -set_range_info (tree name, double_int min, double_int max)
 +set_range_info (tree name, widest_int min, widest_int max)
  {
    gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
    range_info_def *ri = SSA_NAME_RANGE_INFO (name);
      {
        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 VR_VARYING;
  
    /* If min > max, it is VR_ANTI_RANGE.  */
 -  if (ri->min.cmp (ri->max, TYPE_UNSIGNED (TREE_TYPE (name))) == 1)
 +  if (wi::cmp (ri->min, ri->max, TYPE_SIGN (TREE_TYPE (name))) == 1)
      {
        /* VR_ANTI_RANGE ~[min, max] is encoded as [max + 1, min - 1].  */
        range_type = VR_ANTI_RANGE;
 -      *min = ri->max + double_int_one;
 -      *max = ri->min - double_int_one;
 +      *min = ri->max + 1;
 +      *max = ri->min - 1;
      }
    else
    {
    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.
  
diff --combined gcc/tree-ssanames.h
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);
diff --combined gcc/tree-stdarg.c
index 58c2e871ebd22cdd0d1e61e6f408cb68f2793517,2c8aac289b692671da88d901dd2b7accff2b49a8..622d8efe13df658a5239c20ac8404834d73c94b9
@@@ -27,7 -27,12 +27,12 @@@ along with GCC; see the file COPYING3
  #include "langhooks.h"
  #include "gimple-pretty-print.h"
  #include "target.h"
- #include "tree-ssa.h"
+ #include "bitmap.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
  #include "sbitmap.h"
  #include "tree-pass.h"
  #include "tree-stdarg.h"
@@@ -165,9 -170,9 +170,9 @@@ va_list_counter_bump (struct stdarg_inf
        if ((rhs_code == POINTER_PLUS_EXPR
           || rhs_code == PLUS_EXPR)
          && TREE_CODE (rhs1) == SSA_NAME
 -        && host_integerp (gimple_assign_rhs2 (stmt), 1))
 +        && tree_fits_uhwi_p (gimple_assign_rhs2 (stmt)))
        {
 -        ret += tree_low_cst (gimple_assign_rhs2 (stmt), 1);
 +        ret += tree_to_uhwi (gimple_assign_rhs2 (stmt));
          lhs = rhs1;
          continue;
        }
        if (rhs_code == ADDR_EXPR 
          && TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0)) == SSA_NAME
 -        && host_integerp (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1))
 +        && tree_fits_uhwi_p (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1)))
        {
 -        ret += tree_low_cst (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1);
 +        ret += tree_to_uhwi (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1));
          lhs = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
          continue;
        }
        if ((rhs_code == POINTER_PLUS_EXPR
           || rhs_code == PLUS_EXPR)
          && TREE_CODE (rhs1) == SSA_NAME
 -        && host_integerp (gimple_assign_rhs2 (stmt), 1))
 +        && tree_fits_uhwi_p (gimple_assign_rhs2 (stmt)))
        {
 -        val -= tree_low_cst (gimple_assign_rhs2 (stmt), 1);
 +        val -= tree_to_uhwi (gimple_assign_rhs2 (stmt));
          lhs = rhs1;
          continue;
        }
        if (rhs_code == ADDR_EXPR 
          && TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0)) == SSA_NAME
 -        && host_integerp (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1))
 +        && tree_fits_uhwi_p (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1)))
        {
 -        val -= tree_low_cst (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1), 1);
 +        val -= tree_to_uhwi (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1));
          lhs = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
          continue;
        }
@@@ -582,15 -587,15 +587,15 @@@ check_all_va_list_escapes (struct stdar
                  if (rhs_code == MEM_REF
                      && TREE_OPERAND (rhs, 0) == use
                      && TYPE_SIZE_UNIT (TREE_TYPE (rhs))
 -                    && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (rhs)), 1)
 +                    && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (rhs)))
                      && si->offsets[SSA_NAME_VERSION (use)] != -1)
                    {
                      unsigned HOST_WIDE_INT gpr_size;
                      tree access_size = TYPE_SIZE_UNIT (TREE_TYPE (rhs));
  
                      gpr_size = si->offsets[SSA_NAME_VERSION (use)]
 -                               + tree_low_cst (TREE_OPERAND (rhs, 1), 0)
 -                               + tree_low_cst (access_size, 1);
 +                               + tree_to_shwi (TREE_OPERAND (rhs, 1))
 +                               + tree_to_uhwi (access_size);
                      if (gpr_size >= VA_LIST_MAX_GPR_SIZE)
                        cfun->va_list_gpr_size = VA_LIST_MAX_GPR_SIZE;
                      else if (gpr_size > cfun->va_list_gpr_size)
diff --combined gcc/tree-streamer-in.c
index ffc468a56ccb8f72c7a73918adfc103b42a42589,92598e39941eb6a51adfd905a8bf321f83c59e56..c0989c8ff72a2849c0235e8cea18f00cc3c93e07
@@@ -24,7 -24,7 +24,7 @@@ along with GCC; see the file COPYING3
  #include "coretypes.h"
  #include "diagnostic.h"
  #include "tree.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
  #include "tree-streamer.h"
  #include "data-streamer.h"
  #include "streamer-hooks.h"
@@@ -146,9 -146,8 +146,9 @@@ unpack_ts_base_value_fields (struct bit
  static void
  unpack_ts_int_cst_value_fields (struct bitpack_d *bp, tree expr)
  {
 -  TREE_INT_CST_LOW (expr) = bp_unpack_var_len_unsigned (bp);
 -  TREE_INT_CST_HIGH (expr) = bp_unpack_var_len_int (bp);
 +  int i;
 +  for (i = 0; i < TREE_INT_CST_EXT_NUNITS (expr); i++)
 +    TREE_INT_CST_ELT (expr, i) = bp_unpack_var_len_int (bp);
  }
  
  
@@@ -568,12 -567,6 +568,12 @@@ streamer_alloc_tree (struct lto_input_b
        unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
        result = make_tree_binfo (len);
      }
 +  else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
 +    {
 +      unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
 +      unsigned HOST_WIDE_INT ext_len = streamer_read_uhwi (ib);
 +      result = make_int_cst (len, ext_len);
 +    }
    else if (code == CALL_EXPR)
      {
        unsigned HOST_WIDE_INT nargs = streamer_read_uhwi (ib);
diff --combined gcc/tree-streamer-out.c
index 3439bffed5c6ce04edbff5c9189751ad1b2882eb,ea1a0546516d1023821b018ed9a7e8a53887daa1..7161dba1a54a789d3ad4fba9e699716d34b24610
@@@ -25,6 -25,7 +25,7 @@@ along with GCC; see the file COPYING3
  #include "tm.h"
  #include "diagnostic.h"
  #include "tree.h"
+ #include "gimple.h"
  #include "tree-streamer.h"
  #include "data-streamer.h"
  #include "streamer-hooks.h"
@@@ -118,14 -119,10 +119,14 @@@ pack_ts_base_value_fields (struct bitpa
     expression EXPR into bitpack BP.  */
  
  static void
 -pack_ts_int_cst_value_fields (struct bitpack_d *bp, tree expr)
 +pack_ts_int_cst_value_fields (struct bitpack_d *bp, 
 +                            tree expr ATTRIBUTE_UNUSED)
  {
 -  bp_pack_var_len_unsigned (bp, TREE_INT_CST_LOW (expr));
 -  bp_pack_var_len_int (bp, TREE_INT_CST_HIGH (expr));
 +  int i;
 +  /* Note that the number of elements has already been written out in
 +     streamer_write_tree_header.  */
 +  for (i = 0; i < TREE_INT_CST_EXT_NUNITS (expr); i++)
 +    bp_pack_var_len_int (bp, TREE_INT_CST_ELT (expr, i));
  }
  
  
@@@ -960,12 -957,6 +961,12 @@@ streamer_write_tree_header (struct outp
      streamer_write_uhwi (ob, BINFO_N_BASE_BINFOS (expr));
    else if (TREE_CODE (expr) == CALL_EXPR)
      streamer_write_uhwi (ob, call_expr_nargs (expr));
 +  else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
 +    {
 +      gcc_checking_assert (TREE_INT_CST_NUNITS (expr));
 +      streamer_write_uhwi (ob, TREE_INT_CST_NUNITS (expr));
 +      streamer_write_uhwi (ob, TREE_INT_CST_EXT_NUNITS (expr));
 +    }
  }
  
  
  void
  streamer_write_integer_cst (struct output_block *ob, tree cst, bool ref_p)
  {
 +  int i;
 +  int len = TREE_INT_CST_NUNITS (cst);
    gcc_assert (!TREE_OVERFLOW (cst));
    streamer_write_record_start (ob, LTO_integer_cst);
    stream_write_tree (ob, TREE_TYPE (cst), ref_p);
 -  streamer_write_uhwi (ob, TREE_INT_CST_LOW (cst));
 -  streamer_write_hwi (ob, TREE_INT_CST_HIGH (cst));
 +  /* We're effectively streaming a non-sign-extended wide_int here,
 +     so there's no need to stream TREE_INT_CST_EXT_NUNITS or any
 +     array members beyond LEN.  We'll recreate the tree from the
 +     wide_int and the type.  */
 +  streamer_write_uhwi (ob, len);
 +  for (i = 0; i < len; i++)
 +    streamer_write_hwi (ob, TREE_INT_CST_ELT (cst, i));
  }
index 776b8c13306104d57b8cbe4115c62ee73408f369,46b9efe3aa7ef0443dbbb37f7f0d37306ce80823..9486132a0b9f1ce1c83fc23db4e95b59acbc5871
@@@ -31,7 -31,12 +31,12 @@@ Software Foundation, 51 Franklin Street
  #include "flags.h"
  #include "tree.h"
  #include "basic-block.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "tree-ssanames.h"
  #include "tree-pass.h"
  #include "gimple-pretty-print.h"
  #include "cfgloop.h"
@@@ -346,13 -351,15 +351,13 @@@ emit_case_bit_tests (gimple swtch, tre
        else
          test[k].bits++;
  
 -      lo = tree_low_cst (int_const_binop (MINUS_EXPR,
 -                                        CASE_LOW (cs), minval),
 -                       1);
 +      lo = tree_to_uhwi (int_const_binop (MINUS_EXPR,
 +                                        CASE_LOW (cs), minval));
        if (CASE_HIGH (cs) == NULL_TREE)
        hi = lo;
        else
 -      hi = tree_low_cst (int_const_binop (MINUS_EXPR, 
 -                                          CASE_HIGH (cs), minval),
 -                         1);
 +      hi = tree_to_uhwi (int_const_binop (MINUS_EXPR, 
 +                                          CASE_HIGH (cs), minval));
  
        for (j = lo; j <= hi; j++)
          if (j >= HOST_BITS_PER_WIDE_INT)
          if (const & csui) goto target  */
    for (k = 0; k < count; k++)
      {
 -      tmp = build_int_cst_wide (word_type_node, test[k].lo, test[k].hi);
 +      HOST_WIDE_INT a[2];
 +
 +      a[0] = test[k].lo;
 +      a[1] = test[k].hi;
 +      tmp = wide_int_to_tree (word_type_node, 
 +                            wide_int::from_array (a, 2, 
 +                                                  TYPE_PRECISION (word_type_node)));
        tmp = fold_build2 (BIT_AND_EXPR, word_type_node, csui, tmp);
        tmp = force_gimple_operand_gsi (&gsi, tmp,
                                      /*simple=*/true, NULL_TREE,
@@@ -693,13 -694,13 +698,13 @@@ static boo
  check_range (struct switch_conv_info *info)
  {
    gcc_assert (info->range_size);
 -  if (!host_integerp (info->range_size, 1))
 +  if (!tree_fits_uhwi_p (info->range_size))
      {
        info->reason = "index range way too large or otherwise unusable";
        return false;
      }
  
 -  if ((unsigned HOST_WIDE_INT) tree_low_cst (info->range_size, 1)
 +  if ((unsigned HOST_WIDE_INT) tree_to_uhwi (info->range_size)
        > ((unsigned) info->count * SWITCH_CONVERSION_BRANCH_RATIO))
      {
        info->reason = "the maximum range-branch ratio exceeded";
@@@ -801,7 -802,7 +806,7 @@@ create_temp_arrays (struct switch_conv_
    info->target_inbound_names = info->default_values + info->phi_count;
    info->target_outbound_names = info->target_inbound_names + info->phi_count;
    for (i = 0; i < info->phi_count; i++)
 -    vec_alloc (info->constructors[i], tree_low_cst (info->range_size, 1) + 1);
 +    vec_alloc (info->constructors[i], tree_to_uhwi (info->range_size) + 1);
  }
  
  /* Free the arrays created by create_temp_arrays().  The vectors that are
@@@ -880,7 -881,7 +885,7 @@@ build_constructors (gimple swtch, struc
              info->constructors[k]->quick_push (elt);
            }
  
 -        pos = int_const_binop (PLUS_EXPR, pos, integer_one_node);
 +        pos = int_const_binop (PLUS_EXPR, pos, build_int_cst (TREE_TYPE (pos), 1));
        }
        gcc_assert (tree_int_cst_equal (pos, CASE_LOW (cs)));
  
              elt.value = unshare_expr_without_location (val);
              info->constructors[j]->quick_push (elt);
  
 -            pos = int_const_binop (PLUS_EXPR, pos, integer_one_node);
 +            pos = int_const_binop (PLUS_EXPR, pos, build_int_cst (TREE_TYPE (pos), 1));
            } while (!tree_int_cst_lt (high, pos)
                     && tree_int_cst_lt (low, pos));
          j++;
@@@ -960,26 -961,26 +965,26 @@@ array_value_type (gimple swtch, tree ty
  
    FOR_EACH_VEC_SAFE_ELT (info->constructors[num], i, elt)
      {
 -      double_int cst;
 +      wide_int cst;
  
        if (TREE_CODE (elt->value) != INTEGER_CST)
        return type;
  
 -      cst = TREE_INT_CST (elt->value);
 +      cst = elt->value;
        while (1)
        {
          unsigned int prec = GET_MODE_BITSIZE (mode);
          if (prec > HOST_BITS_PER_WIDE_INT)
            return type;
  
 -        if (sign >= 0 && cst == cst.zext (prec))
 +        if (sign >= 0 && cst == wi::zext (cst, prec))
            {
 -            if (sign == 0 && cst == cst.sext (prec))
 +            if (sign == 0 && cst == wi::sext (cst, prec))
                break;
              sign = 1;
              break;
            }
 -        if (sign <= 0 && cst == cst.sext (prec))
 +        if (sign <= 0 && cst == wi::sext (cst, prec))
            {
              sign = -1;
              break;
index 3764cfb98f840dcc4eb27fe45ed9270738df4658,fb3fe94240b1b854be4f1589d801ef5c55ea2aa4..919db21fb96d5b3ac37e40a98c4d37415709648a
@@@ -30,7 -30,14 +30,14 @@@ along with GCC; see the file COPYING3
  #include "target.h"
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-ivopts.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop.h"
  #include "dumpfile.h"
  #include "cfgloop.h"
  #include "tree-chrec.h"
@@@ -107,7 -114,7 +114,7 @@@ vect_get_smallest_scalar_type (gimple s
    tree scalar_type = gimple_expr_type (stmt);
    HOST_WIDE_INT lhs, rhs;
  
 -  lhs = rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (scalar_type));
 +  lhs = rhs = tree_to_hwi (TYPE_SIZE_UNIT (scalar_type));
  
    if (is_gimple_assign (stmt)
        && (gimple_assign_cast_p (stmt)
      {
        tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
  
 -      rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (rhs_type));
 +      rhs = tree_to_hwi (TYPE_SIZE_UNIT (rhs_type));
        if (rhs < lhs)
          scalar_type = rhs_type;
      }
@@@ -569,16 -576,16 +576,16 @@@ vect_slp_analyze_data_ref_dependence (s
      return true;
  
    /* Check the types.  */
 -  type_size_a = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))));
 -  type_size_b = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
 +  type_size_a = tree_to_hwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))));
 +  type_size_b = tree_to_hwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
  
    if (type_size_a != type_size_b
        || !types_compatible_p (TREE_TYPE (DR_REF (dra)),
                                TREE_TYPE (DR_REF (drb))))
      return true;
  
 -  init_a = TREE_INT_CST_LOW (DR_INIT (dra));
 -  init_b = TREE_INT_CST_LOW (DR_INIT (drb));
 +  init_a = tree_to_hwi (DR_INIT (dra));
 +  init_b = tree_to_hwi (DR_INIT (drb));
  
    /* Two different locations - no dependence.  */
    if (init_a != init_b)
@@@ -681,7 -688,7 +688,7 @@@ vect_compute_data_ref_alignment (struc
    if (loop && nested_in_vect_loop_p (loop, stmt))
      {
        tree step = DR_STEP (dr);
 -      HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
 +      HOST_WIDE_INT dr_step = tree_to_hwi (step);
  
        if (dr_step % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0)
          {
    if (!loop)
      {
        tree step = DR_STEP (dr);
 -      HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
 +      HOST_WIDE_INT dr_step = tree_to_hwi (step);
  
        if (dr_step % GET_MODE_SIZE (TYPE_MODE (vectype)) != 0)
        {
    /* Modulo alignment.  */
    misalign = size_binop (FLOOR_MOD_EXPR, misalign, alignment);
  
 -  if (!host_integerp (misalign, 1))
 +  if (!tree_fits_uhwi_p (misalign))
      {
        /* Negative or overflowed misalignment value.  */
        if (dump_enabled_p ())
        return false;
      }
  
 -  SET_DR_MISALIGNMENT (dr, TREE_INT_CST_LOW (misalign));
 +  SET_DR_MISALIGNMENT (dr, tree_to_hwi (misalign));
  
    if (dump_enabled_p ())
      {
@@@ -985,10 -992,10 +992,10 @@@ vect_verify_datarefs_alignment (loop_ve
  static bool
  not_size_aligned (tree exp)
  {
 -  if (!host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1))
 +  if (!tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp))))
      return true;
  
 -  return (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))
 +  return (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp)))
          > get_object_alignment (exp));
  }
  
@@@ -2030,12 -2037,12 +2037,12 @@@ vect_analyze_group_access (struct data_
  {
    tree step = DR_STEP (dr);
    tree scalar_type = TREE_TYPE (DR_REF (dr));
 -  HOST_WIDE_INT type_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (scalar_type));
 +  HOST_WIDE_INT type_size = tree_to_hwi (TYPE_SIZE_UNIT (scalar_type));
    gimple stmt = DR_STMT (dr);
    stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
    bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
 -  HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
 +  HOST_WIDE_INT dr_step = tree_to_hwi (step);
    HOST_WIDE_INT groupsize, last_accessed_element = 1;
    bool slp_impossible = false;
    struct loop *loop = NULL;
  
            /* Check that the distance between two accesses is equal to the type
               size. Otherwise, we have gaps.  */
 -          diff = (TREE_INT_CST_LOW (DR_INIT (data_ref))
 -                  - TREE_INT_CST_LOW (prev_init)) / type_size;
 +          diff = (tree_to_hwi (DR_INIT (data_ref))
 +                  - tree_to_hwi (prev_init)) / type_size;
          if (diff != 1)
            {
              /* FORNOW: SLP of accesses with gaps is not supported.  */
@@@ -2347,7 -2354,7 +2354,7 @@@ vect_analyze_data_ref_access (struct da
    /* Consecutive?  */
    if (TREE_CODE (step) == INTEGER_CST)
      {
 -      HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
 +      HOST_WIDE_INT dr_step = tree_to_hwi (step);
        if (!tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type))
          || (dr_step < 0
              && !compare_tree_int (TYPE_SIZE_UNIT (scalar_type), -dr_step)))
@@@ -2569,11 -2576,11 +2576,11 @@@ vect_analyze_data_ref_accesses (loop_ve
          /* Check that the data-refs have the same constant size and step.  */
          tree sza = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra)));
          tree szb = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb)));
 -        if (!host_integerp (sza, 1)
 -            || !host_integerp (szb, 1)
 +        if (!tree_fits_uhwi_p (sza)
 +            || !tree_fits_uhwi_p (szb)
              || !tree_int_cst_equal (sza, szb)
 -            || !host_integerp (DR_STEP (dra), 0)
 -            || !host_integerp (DR_STEP (drb), 0)
 +            || !tree_fits_shwi_p (DR_STEP (dra))
 +            || !tree_fits_shwi_p (DR_STEP (drb))
              || !tree_int_cst_equal (DR_STEP (dra), DR_STEP (drb)))
            break;
  
            break;
  
          /* Sorting has ensured that DR_INIT (dra) <= DR_INIT (drb).  */
 -        HOST_WIDE_INT init_a = TREE_INT_CST_LOW (DR_INIT (dra));
 -        HOST_WIDE_INT init_b = TREE_INT_CST_LOW (DR_INIT (drb));
 +        HOST_WIDE_INT init_a = tree_to_hwi (DR_INIT (dra));
 +        HOST_WIDE_INT init_b = tree_to_hwi (DR_INIT (drb));
          gcc_assert (init_a < init_b);
  
          /* If init_b == init_a + the size of the type * k, we have an
             interleaving, and DRA is accessed before DRB.  */
 -        HOST_WIDE_INT type_size_a = TREE_INT_CST_LOW (sza);
 +        HOST_WIDE_INT type_size_a = tree_to_hwi (sza);
          if ((init_b - init_a) % type_size_a != 0)
            break;
  
          /* The step (if not zero) is greater than the difference between
             data-refs' inits.  This splits groups into suitable sizes.  */
 -        HOST_WIDE_INT step = TREE_INT_CST_LOW (DR_STEP (dra));
 +        HOST_WIDE_INT step = tree_to_hwi (DR_STEP (dra));
          if (step != 0 && step <= (init_b - init_a))
            break;
  
@@@ -2764,8 -2771,8 +2771,8 @@@ vect_check_gather (gimple stmt, loop_ve
        {
          if (off == NULL_TREE)
            {
 -            double_int moff = mem_ref_offset (base);
 -            off = double_int_to_tree (sizetype, moff);
 +            offset_int moff = mem_ref_offset (base);
 +            off = wide_int_to_tree (sizetype, moff);
            }
          else
            off = size_binop (PLUS_EXPR, off,
            }
          break;
        case MULT_EXPR:
 -        if (scale == 1 && host_integerp (op1, 0))
 +        if (scale == 1 && tree_fits_shwi_p (op1))
            {
 -            scale = tree_low_cst (op1, 0);
 +            scale = tree_to_shwi (op1);
              off = op0;
              continue;
            }
@@@ -3060,7 -3067,7 +3067,7 @@@ again
                      STRIP_NOPS (off);
                      if (TREE_CODE (DR_INIT (newdr)) == INTEGER_CST
                          && TREE_CODE (off) == MULT_EXPR
 -                        && host_integerp (TREE_OPERAND (off, 1), 1))
 +                        && tree_fits_uhwi_p (TREE_OPERAND (off, 1)))
                        {
                          tree step = TREE_OPERAND (off, 1);
                          off = TREE_OPERAND (off, 0);
@@@ -4931,7 -4938,7 +4938,7 @@@ vect_supportable_dr_alignment (struct d
        {
          tree vectype = STMT_VINFO_VECTYPE (stmt_info);
          if ((nested_in_vect_loop
 -             && (TREE_INT_CST_LOW (DR_STEP (dr))
 +             && (tree_to_hwi (DR_STEP (dr))
                   != GET_MODE_SIZE (TYPE_MODE (vectype))))
                || !loop_vinfo)
            return dr_explicit_realign;
diff --combined gcc/tree-vect-generic.c
index d242959b1315885abd80e433ffb7f5fbaac8a34b,1521b2ba2c5833a9e2a245304c7073ea13f5c27b..d58ddffb50b78184297cdb2dbe456cea92c3ce13
@@@ -23,8 -23,10 +23,10 @@@ along with GCC; see the file COPYING3
  #include "tree.h"
  #include "tm.h"
  #include "langhooks.h"
- #include "tree-ssa.h"
  #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-ssanames.h"
  #include "tree-iterator.h"
  #include "tree-pass.h"
  #include "flags.h"
@@@ -45,11 -47,11 +47,11 @@@ static void expand_vector_operations_1 
  static tree
  build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
  {
 -  int width = tree_low_cst (TYPE_SIZE (inner_type), 1);
 -  int n = HOST_BITS_PER_WIDE_INT / width;
 -  unsigned HOST_WIDE_INT low, high, mask;
 -  tree ret;
 -
 +  int width = tree_to_uhwi (TYPE_SIZE (inner_type));
 +  int n = TYPE_PRECISION (type) / width;
 +  unsigned HOST_WIDE_INT low, mask;
 +  HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
 +  int i;
    gcc_assert (n);
  
    if (width == HOST_BITS_PER_WIDE_INT)
        low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
      }
  
 -  if (TYPE_PRECISION (type) < HOST_BITS_PER_WIDE_INT)
 -    low &= ((HOST_WIDE_INT)1 << TYPE_PRECISION (type)) - 1, high = 0;
 -  else if (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT)
 -    high = 0;
 -  else if (TYPE_PRECISION (type) == HOST_BITS_PER_DOUBLE_INT)
 -    high = low;
 -  else
 -    gcc_unreachable ();
 +  for (i = 0; i < n; i++)
 +    a[i] = low;
  
 -  ret = build_int_cst_wide (type, low, high);
 -  return ret;
 +  return wide_int_to_tree 
 +    (type, wide_int::from_array (a, n, TYPE_PRECISION (type)));
  }
  
  static GTY(()) tree vector_inner_type;
@@@ -228,8 -236,8 +230,8 @@@ expand_vector_piecewise (gimple_stmt_it
    tree part_width = TYPE_SIZE (inner_type);
    tree index = bitsize_int (0);
    int nunits = TYPE_VECTOR_SUBPARTS (type);
 -  int delta = tree_low_cst (part_width, 1)
 -            / tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
 +  int delta = tree_to_uhwi (part_width)
 +            / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
    int i;
    location_t loc = gimple_location (gsi_stmt (*gsi));
  
@@@ -262,7 -270,7 +264,7 @@@ expand_vector_parallel (gimple_stmt_ite
  {
    tree result, compute_type;
    enum machine_mode mode;
 -  int n_words = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
 +  int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
    location_t loc = gimple_location (gsi_stmt (*gsi));
  
    /* We have three strategies.  If the type is already correct, just do
    else
      {
        /* Use a single scalar operation with a mode no wider than word_mode.  */
 -      mode = mode_for_size (tree_low_cst (TYPE_SIZE (type), 1), MODE_INT, 0);
 +      mode = mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), MODE_INT, 0);
        compute_type = lang_hooks.types.type_for_mode (mode, 1);
        result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code);
        warning_at (loc, OPT_Wvector_operation_performance,
@@@ -307,7 -315,7 +309,7 @@@ expand_vector_addition (gimple_stmt_ite
                        tree type, tree a, tree b, enum tree_code code)
  {
    int parts_per_word = UNITS_PER_WORD
 -                     / tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
 +                     / tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
  
    if (INTEGRAL_TYPE_P (TREE_TYPE (type))
        && parts_per_word >= 4
@@@ -398,8 -406,7 +400,8 @@@ expand_vector_divmod (gimple_stmt_itera
    unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
    int prec = TYPE_PRECISION (TREE_TYPE (type));
    int dummy_int;
 -  unsigned int i, unsignedp = TYPE_UNSIGNED (TREE_TYPE (type));
 +  unsigned int i; 
 +  signop sign_p = TYPE_SIGN (TREE_TYPE (type));
    unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
    tree *vec;
    tree cur_op, mulcst, tem;
        tree cst = VECTOR_CST_ELT (op1, i);
        unsigned HOST_WIDE_INT ml;
  
 -      if (!host_integerp (cst, unsignedp) || integer_zerop (cst))
 +      if (!tree_fits_hwi_p (cst, sign_p) || integer_zerop (cst))
        return NULL_TREE;
        pre_shifts[i] = 0;
        post_shifts[i] = 0;
        }
        if (mode == -2)
        continue;
 -      if (unsignedp)
 +      if (sign_p == UNSIGNED)
        {
          unsigned HOST_WIDE_INT mh;
 -        unsigned HOST_WIDE_INT d = tree_low_cst (cst, 1) & mask;
 +        unsigned HOST_WIDE_INT d = tree_to_uhwi (cst) & mask;
  
          if (d >= ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))
            /* FIXME: Can transform this into op0 >= op1 ? 1 : 0.  */
                      unsigned HOST_WIDE_INT d2;
                      int this_pre_shift;
  
 -                    if (!host_integerp (cst2, 1))
 +                    if (!tree_fits_uhwi_p (cst2))
                        return NULL_TREE;
 -                    d2 = tree_low_cst (cst2, 1) & mask;
 +                    d2 = tree_to_uhwi (cst2) & mask;
                      if (d2 == 0)
                        return NULL_TREE;
                      this_pre_shift = floor_log2 (d2 & -d2);
        }
        else
        {
 -        HOST_WIDE_INT d = tree_low_cst (cst, 0);
 +        HOST_WIDE_INT d = tree_to_shwi (cst);
          unsigned HOST_WIDE_INT abs_d;
  
          if (d == -1)
    if (use_pow2)
      {
        tree addend = NULL_TREE;
 -      if (!unsignedp)
 +      if (sign_p == SIGNED)
        {
          tree uns_type;
  
        }
        if (code == TRUNC_DIV_EXPR)
        {
 -        if (unsignedp)
 +        if (sign_p == UNSIGNED)
            {
              /* q = op0 >> shift;  */
              cur_op = add_rshift (gsi, type, op0, shifts);
          if (op != unknown_optab
              && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
            {
 -            if (unsignedp)
 +            if (sign_p == UNSIGNED)
                /* r = op0 & mask;  */
                return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
              else if (addend != NULL_TREE)
    switch (mode)
      {
      case 0:
 -      gcc_assert (unsignedp);
 +      gcc_assert (sign_p == UNSIGNED);
        /* t1 = oprnd0 >> pre_shift;
         t2 = t1 h* ml;
         q = t2 >> post_shift;  */
        return NULL_TREE;
        break;
      case 1:
 -      gcc_assert (unsignedp);
 +      gcc_assert (sign_p == UNSIGNED);
        for (i = 0; i < nunits; i++)
        {
          shift_temps[i] = 1;
      case 3:
      case 4:
      case 5:
 -      gcc_assert (!unsignedp);
 +      gcc_assert (sign_p == SIGNED);
        for (i = 0; i < nunits; i++)
        shift_temps[i] = prec - 1;
        break;
@@@ -1044,8 -1051,8 +1046,8 @@@ vector_element (gimple_stmt_iterator *g
  
        /* Given that we're about to compute a binary modulus,
         we don't care about the high bits of the value.  */
 -      index = TREE_INT_CST_LOW (idx);
 -      if (!host_integerp (idx, 1) || index >= elements)
 +      index = tree_to_hwi (idx);
 +      if (!tree_fits_uhwi_p (idx) || index >= elements)
        {
          index &= elements - 1;
          idx = build_int_cst (TREE_TYPE (idx), index);
@@@ -1150,7 -1157,7 +1152,7 @@@ lower_vec_perm (gimple_stmt_iterator *g
        unsigned char *sel_int = XALLOCAVEC (unsigned char, elements);
  
        for (i = 0; i < elements; ++i)
 -      sel_int[i] = (TREE_INT_CST_LOW (VECTOR_CST_ELT (mask, i))
 +      sel_int[i] = (tree_to_hwi (VECTOR_CST_ELT (mask, i))
                      & (2 * elements - 1));
  
        if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int))
          {
          unsigned HOST_WIDE_INT index;
  
 -        index = TREE_INT_CST_LOW (i_val);
 -        if (!host_integerp (i_val, 1) || index >= elements)
 +        index = tree_to_hwi (i_val);
 +        if (!tree_fits_uhwi_p (i_val) || index >= elements)
            i_val = build_int_cst (mask_elt_type, index & (elements - 1));
  
            if (two_operand_p && (index & elements) != 0)
index 1fe20d91cb448e5303490938b7babee4f8c33f52,00a3661385e0ca7cf2a440f0cd8fbeb94e0ac1b5..9b879a4125c1a14bcb315d7b7f0e6f8c850a27fd
@@@ -28,6 -28,14 +28,14 @@@ along with GCC; see the file COPYING3
  #include "tree.h"
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-into-ssa.h"
  #include "tree-ssa.h"
  #include "tree-pass.h"
  #include "cfgloop.h"
@@@ -107,7 -115,7 +115,7 @@@ typedef struc
     with a PHI DEF that would soon become non-dominant, and when we got
     to the suitable one, it wouldn't have anything to substitute any
     more.  */
- static vec<adjust_info, va_stack> adjust_vec;
+ static vec<adjust_info, va_heap> adjust_vec;
  
  /* Adjust any debug stmts that referenced AI->from values to use the
     loop-closed AI->to, if the references are dominated by AI->bb and
@@@ -1125,7 -1133,7 +1133,7 @@@ slpeel_tree_peel_loop_to_edge (struct l
    if (MAY_HAVE_DEBUG_STMTS)
      {
        gcc_assert (!adjust_vec.exists ());
-       vec_stack_alloc (adjust_info, adjust_vec, 32);
+       adjust_vec.create (32);
      }
  
    if (e == exit_e)
@@@ -1429,7 -1437,7 +1437,7 @@@ vect_build_loop_niters (loop_vec_info l
   and places them at the loop preheader edge or in COND_EXPR_STMT_LIST
   if that is non-NULL.  */
  
static void
+ void
  vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
                                 tree *ni_name_ptr,
                                 tree *ratio_mult_vf_name_ptr,
@@@ -1817,7 -1825,7 +1825,7 @@@ vect_do_peeling_for_loop_bound (loop_ve
              : LOOP_VINFO_VECT_FACTOR (loop_vinfo)) - 2;
    if (check_profitability)
      max_iter = MAX (max_iter, (int) th - 1);
 -  record_niter_bound (new_loop, double_int::from_shwi (max_iter), false, true);
 +  record_niter_bound (new_loop, max_iter, false, true);
    dump_printf (MSG_NOTE,
                 "Setting upper bound of nb iterations for epilogue "
                 "loop to %d\n", max_iter);
@@@ -2053,7 -2061,7 +2061,7 @@@ vect_do_peeling_for_alignment (loop_vec
    max_iter = LOOP_VINFO_VECT_FACTOR (loop_vinfo) - 2;
    if (check_profitability)
      max_iter = MAX (max_iter, (int) th - 1);
 -  record_niter_bound (new_loop, double_int::from_shwi (max_iter), false, true);
 +  record_niter_bound (new_loop, max_iter, false, true);
    dump_printf (MSG_NOTE,
                 "Setting upper bound of nb iterations for prologue "
                 "loop to %d\n", max_iter);
diff --combined gcc/tree-vect-loop.c
index bb700d0e60c8dbff831014ce750f01b29f932395,d5f86ad00a7f6a7a72a458b1b82b1ce4d22a6551..1652b11bcaa610f51b6b5c77ec5d896bf75d2e39
@@@ -28,7 -28,14 +28,14 @@@ along with GCC; see the file COPYING3
  #include "tree.h"
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-ivopts.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
  #include "tree-pass.h"
  #include "cfgloop.h"
  #include "expr.h"
@@@ -584,8 -591,7 +591,7 @@@ vect_analyze_scalar_cycles_1 (loop_vec_
  {
    basic_block bb = loop->header;
    tree init, step;
-   vec<gimple> worklist;
-   worklist.create (64);
+   stack_vec<gimple, 64> worklist;
    gimple_stmt_iterator gsi;
    bool double_reduc;
  
            dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                           "Unknown def-use cycle pattern.\n");
      }
-   worklist.release ();
  }
  
  
@@@ -1265,7 -1269,7 +1269,7 @@@ vect_analyze_loop_form (struct loop *lo
            dump_printf (MSG_NOTE, "\n");
          }
      }
 -  else if (TREE_INT_CST_LOW (number_of_iterations) == 0)
 +  else if (tree_to_hwi (number_of_iterations) == 0)
      {
        if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@@ -1579,9 -1583,9 +1583,9 @@@ vect_analyze_loop_operations (loop_vec_
        return false;
      }
  
-   if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
-       || LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0
-       || LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
+   if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo)
+       || ((int) tree_ctz (LOOP_VINFO_NITERS (loop_vinfo))
+         < exact_log2 (vectorization_factor)))
      {
        if (dump_enabled_p ())
          dump_printf_loc (MSG_NOTE, vect_location, "epilog loop required.\n");
@@@ -3092,10 -3096,10 +3096,10 @@@ vect_model_reduction_cost (stmt_vec_inf
        }
        else
        {
 -        int vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
 +        int vec_size_in_bits = tree_to_uhwi (TYPE_SIZE (vectype));
          tree bitsize =
            TYPE_SIZE (TREE_TYPE (gimple_assign_lhs (orig_stmt)));
 -        int element_bitsize = tree_low_cst (bitsize, 1);
 +        int element_bitsize = tree_to_uhwi (bitsize);
          int nelements = vec_size_in_bits / element_bitsize;
  
          optab = optab_for_tree_code (code, vectype, optab_default);
@@@ -3607,7 -3611,7 +3611,7 @@@ get_initial_def_for_reduction (gimple s
        if (SCALAR_FLOAT_TYPE_P (scalar_type))
          init_value = build_real (scalar_type, TREE_REAL_CST (init_val));
        else
 -        init_value = build_int_cst (scalar_type, TREE_INT_CST_LOW (init_val));
 +        init_value = build_int_cst (scalar_type, tree_to_hwi (init_val));
      }
    else
      init_value = init_val;
@@@ -4108,8 -4112,8 +4112,8 @@@ vect_create_epilog_for_reduction (vec<t
        enum tree_code shift_code = ERROR_MARK;
        bool have_whole_vector_shift = true;
        int bit_offset;
 -      int element_bitsize = tree_low_cst (bitsize, 1);
 -      int vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
 +      int element_bitsize = tree_to_uhwi (bitsize);
 +      int vec_size_in_bits = tree_to_uhwi (TYPE_SIZE (vectype));
        tree vec_temp;
  
        if (optab_handler (vec_shr_optab, mode) != CODE_FOR_nothing)
              dump_printf_loc (MSG_NOTE, vect_location,
                             "Reduce using scalar code.\n");
  
 -          vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
 +          vec_size_in_bits = tree_to_uhwi (TYPE_SIZE (vectype));
            FOR_EACH_VEC_ELT (new_phis, i, new_phi)
              {
                if (gimple_code (new_phi) == GIMPLE_PHI)
@@@ -5649,15 -5653,20 +5653,20 @@@ vect_transform_loop (loop_vec_info loop
       will remain scalar and will compute the remaining (n%VF) iterations.
       (VF is the vectorization factor).  */
  
-   if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
-        || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
-          && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0)
-        || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
+   if ((int) tree_ctz (LOOP_VINFO_NITERS (loop_vinfo))
+       < exact_log2 (vectorization_factor)
+       || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
      vect_do_peeling_for_loop_bound (loop_vinfo, &ratio,
                                    th, check_profitability);
-   else
+   else if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
      ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)),
                LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor);
+   else
+     {
+       tree ni_name, ratio_mult_vf;
+       vect_generate_tmps_on_preheader (loop_vinfo, &ni_name, &ratio_mult_vf,
+                                      &ratio, NULL);
+     }
  
    /* 1) Make sure the loop header has exactly two entries
       2) Make sure we have a preheader basic block.  */
    scale_loop_profile (loop, GCOV_COMPUTE_SCALE (1, vectorization_factor),
                      expected_iterations / vectorization_factor);
    loop->nb_iterations_upper_bound
 -    = loop->nb_iterations_upper_bound.udiv (double_int::from_uhwi (vectorization_factor),
 -                                          FLOOR_DIV_EXPR);
 +    = wi::udiv_floor (loop->nb_iterations_upper_bound, vectorization_factor);
    if (LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)
 -      && loop->nb_iterations_upper_bound != double_int_zero)
 -    loop->nb_iterations_upper_bound = loop->nb_iterations_upper_bound - double_int_one;
 +      && loop->nb_iterations_upper_bound != 0)
 +    loop->nb_iterations_upper_bound = loop->nb_iterations_upper_bound - 1;
    if (loop->any_estimate)
      {
        loop->nb_iterations_estimate
 -        = loop->nb_iterations_estimate.udiv (double_int::from_uhwi (vectorization_factor),
 -                                           FLOOR_DIV_EXPR);
 +        = wi::udiv_floor (loop->nb_iterations_estimate, vectorization_factor);
         if (LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)
 -         && loop->nb_iterations_estimate != double_int_zero)
 -       loop->nb_iterations_estimate = loop->nb_iterations_estimate - double_int_one;
 +         && loop->nb_iterations_estimate != 0)
 +       loop->nb_iterations_estimate = loop->nb_iterations_estimate - 1;
      }
  
    if (dump_enabled_p ())
diff --combined gcc/tree-vect-patterns.c
index e92222324793d838efa79088d115ab96c753144d,099880488bc41587c467f8aa1b354eb3b9d0f590..5075246a19b05f87b750f1d68737b228ebee0b5b
@@@ -27,7 -27,11 +27,11 @@@ along with GCC; see the file COPYING3
  #include "target.h"
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
  #include "cfgloop.h"
  #include "expr.h"
  #include "optabs.h"
@@@ -777,8 -781,8 +781,8 @@@ vect_recog_pow_pattern (vec<gimple> *st
    *type_out = NULL_TREE;
  
    /* Catch squaring.  */
 -  if ((host_integerp (exp, 0)
 -       && tree_low_cst (exp, 0) == 2)
 +  if ((tree_fits_shwi_p (exp)
 +       && tree_to_shwi (exp) == 2)
        || (TREE_CODE (exp) == REAL_CST
            && REAL_VALUES_EQUAL (TREE_REAL_CST (exp), dconst2)))
      {
@@@ -1629,14 -1633,14 +1633,14 @@@ vect_recog_rotate_pattern (vec<gimple> 
  
    if (TREE_CODE (def) == INTEGER_CST)
      {
 -      if (!host_integerp (def, 1)
 -        || (unsigned HOST_WIDE_INT) tree_low_cst (def, 1)
 +      if (!tree_fits_uhwi_p (def)
 +        || (unsigned HOST_WIDE_INT) tree_to_uhwi (def)
             >= GET_MODE_PRECISION (TYPE_MODE (type))
          || integer_zerop (def))
        return NULL;
        def2 = build_int_cst (stype,
                            GET_MODE_PRECISION (TYPE_MODE (type))
 -                          - tree_low_cst (def, 1));
 +                          - tree_to_uhwi (def));
      }
    else
      {
@@@ -2059,7 -2063,7 +2063,7 @@@ vect_recog_divmod_pattern (vec<gimple> 
        return pattern_stmt;
      }
  
 -  if (!host_integerp (oprnd1, TYPE_UNSIGNED (itype))
 +  if (!tree_fits_hwi_p (oprnd1, TYPE_SIGN (itype))
        || integer_zerop (oprnd1)
        || prec > HOST_BITS_PER_WIDE_INT)
      return NULL;
      {
        unsigned HOST_WIDE_INT mh, ml;
        int pre_shift, post_shift;
 -      unsigned HOST_WIDE_INT d = tree_low_cst (oprnd1, 1)
 +      unsigned HOST_WIDE_INT d = tree_to_uhwi (oprnd1)
                                 & GET_MODE_MASK (TYPE_MODE (itype));
        tree t1, t2, t3, t4;
  
      {
        unsigned HOST_WIDE_INT ml;
        int post_shift;
 -      HOST_WIDE_INT d = tree_low_cst (oprnd1, 0);
 +      HOST_WIDE_INT d = tree_to_shwi (oprnd1);
        unsigned HOST_WIDE_INT abs_d;
        bool add = false;
        tree t1, t2, t3, t4;
        if (post_shift >= prec)
        return NULL;
  
-       /* t1 = oprnd1 h* ml;  */
+       /* t1 = oprnd0 h* ml;  */
        t1 = vect_recog_temp_ssa_var (itype, NULL);
        def_stmt
        = gimple_build_assign_with_ops (MULT_HIGHPART_EXPR, t1, oprnd0,
                                        build_int_cst (itype, ml));
-       append_pattern_def_seq (stmt_vinfo, def_stmt);
  
        if (add)
        {
          /* t2 = t1 + oprnd0;  */
+         append_pattern_def_seq (stmt_vinfo, def_stmt);
          t2 = vect_recog_temp_ssa_var (itype, NULL);
          def_stmt
            = gimple_build_assign_with_ops (PLUS_EXPR, t2, t1, oprnd0);
-         append_pattern_def_seq (stmt_vinfo, def_stmt);
        }
        else
        t2 = t1;
        if (post_shift)
        {
          /* t3 = t2 >> post_shift;  */
+         append_pattern_def_seq (stmt_vinfo, def_stmt);
          t3 = vect_recog_temp_ssa_var (itype, NULL);
          def_stmt
            = gimple_build_assign_with_ops (RSHIFT_EXPR, t3, t2,
                                            build_int_cst (itype, post_shift));
-         append_pattern_def_seq (stmt_vinfo, def_stmt);
        }
        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)
@@@ -3174,8 -3207,7 +3207,7 @@@ vect_pattern_recog (loop_vec_info loop_
    gimple_stmt_iterator si;
    unsigned int i, j;
    vect_recog_func_ptr vect_recog_func;
-   vec<gimple> stmts_to_replace;
-   stmts_to_replace.create (1);
+   stack_vec<gimple, 1> stmts_to_replace;
    gimple stmt;
  
    if (dump_enabled_p ())
              }
          }
      }
-   stmts_to_replace.release ();
  }
diff --combined gcc/tree-vect-stmts.c
index ae2abba530dc654c17be336368e0d14ed40c4ee5,c1ba3c7eedb2e6bb3dbff34535bb8c4715f256d9..3a9d6298e663e4cc0060bcd79f7aa5b5e12247b8
@@@ -29,7 -29,13 +29,13 @@@ along with GCC; see the file COPYING3
  #include "target.h"
  #include "basic-block.h"
  #include "gimple-pretty-print.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-manip.h"
  #include "cfgloop.h"
  #include "expr.h"
  #include "recog.h"            /* FIXME: for insn_data */
@@@ -574,7 -580,6 +580,6 @@@ process_use (gimple stmt, tree use, loo
  bool
  vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
  {
-   vec<gimple> worklist;
    struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
    basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
    unsigned int nbbs = loop->num_nodes;
      dump_printf_loc (MSG_NOTE, vect_location,
                       "=== vect_mark_stmts_to_be_vectorized ===\n");
  
-   worklist.create (64);
+   stack_vec<gimple, 64> worklist;
  
    /* 1. Init worklist.  */
    for (i = 0; i < nbbs; i++)
                  if (dump_enabled_p ())
                    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                                       "unsupported use of reduction.\n");
-                 worklist.release ();
                  return false;
              }
  
                    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                                     "unsupported use of nested cycle.\n");
  
-                 worklist.release ();
                  return false;
                }
  
                    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                                     "unsupported use of double reduction.\n");
  
-                 worklist.release ();
                  return false;
                }
  
                                    live_p, relevant, &worklist, false)
                      || !process_use (stmt, TREE_OPERAND (op, 1), loop_vinfo,
                                       live_p, relevant, &worklist, false))
-                   {
-                     worklist.release ();
-                     return false;
-                   }
+         return false;
                  i = 2;
                }
              for (; i < gimple_num_ops (stmt); i++)
                  op = gimple_op (stmt, i);
                    if (!process_use (stmt, op, loop_vinfo, live_p, relevant,
                                    &worklist, false))
-                     {
-                       worklist.release ();
-                       return false;
-                     }
+                     return false;
                   }
              }
            else if (is_gimple_call (stmt))
                    tree arg = gimple_call_arg (stmt, i);
                    if (!process_use (stmt, arg, loop_vinfo, live_p, relevant,
                                    &worklist, false))
-                     {
-                       worklist.release ();
-                       return false;
-                     }
+                     return false;
                  }
              }
          }
              tree op = USE_FROM_PTR (use_p);
              if (!process_use (stmt, op, loop_vinfo, live_p, relevant,
                              &worklist, false))
-               {
-                 worklist.release ();
-                 return false;
-               }
+               return false;
            }
  
        if (STMT_VINFO_GATHER_P (stmt_vinfo))
          gcc_assert (decl);
          if (!process_use (stmt, off, loop_vinfo, live_p, relevant,
                            &worklist, true))
-           {
-             worklist.release ();
-             return false;
-           }
+       return false;
        }
      } /* while worklist */
  
-   worklist.release ();
    return true;
  }
  
@@@ -5026,7 -5012,7 +5012,7 @@@ vectorizable_load (gimple stmt, gimple_
       nested within an outer-loop that is being vectorized.  */
  
    if (nested_in_vect_loop
 -      && (TREE_INT_CST_LOW (DR_STEP (dr))
 +      && (tree_to_hwi (DR_STEP (dr))
          % GET_MODE_SIZE (TYPE_MODE (vectype)) != 0))
      {
        gcc_assert (alignment_support_scheme != dr_explicit_realign_optimized);
@@@ -5546,11 -5532,9 +5532,9 @@@ vectorizable_condition (gimple stmt, gi
        {
            if (slp_node)
              {
-               vec<tree> ops;
-             ops.create (4);
-             vec<vec<tree> > vec_defs;
+               stack_vec<tree, 4> ops;
+             stack_vec<vec<tree>, 4> vec_defs;
  
-             vec_defs.create (4);
                ops.safe_push (TREE_OPERAND (cond_expr, 0));
                ops.safe_push (TREE_OPERAND (cond_expr, 1));
                ops.safe_push (then_clause);
diff --combined gcc/tree-vectorizer.h
index 2dc0c702fa8ba19a97d2881650e580562530a23d,a2f482ddad522e39d1ca62ce6e559671d742d294..97dbfb5650712da986db599c7de459fb7b59ee7c
@@@ -330,7 -330,7 +330,7 @@@ typedef struct _loop_vec_info 
  #define LOOP_VINFO_LOOP_NEST(L)            (L)->loop_nest
  #define LOOP_VINFO_DATAREFS(L)             (L)->datarefs
  #define LOOP_VINFO_DDRS(L)                 (L)->ddrs
 -#define LOOP_VINFO_INT_NITERS(L)           (TREE_INT_CST_LOW ((L)->num_iters))
 +#define LOOP_VINFO_INT_NITERS(L)           (tree_to_hwi ((L)->num_iters))
  #define LOOP_PEELING_FOR_ALIGNMENT(L)      (L)->peeling_for_alignment
  #define LOOP_VINFO_UNALIGNED_DR(L)         (L)->unaligned_dr
  #define LOOP_VINFO_MAY_MISALIGN_STMTS(L)   (L)->may_misalign_stmts
  (L)->may_alias_ddrs.length () > 0
  
  #define NITERS_KNOWN_P(n)                     \
 -(host_integerp ((n),0)                        \
 -&& TREE_INT_CST_LOW ((n)) > 0)
 +(tree_fits_shwi_p ((n))                        \
 +&& tree_to_shwi ((n)) > 0)
  
  #define LOOP_VINFO_NITERS_KNOWN_P(L)          \
  NITERS_KNOWN_P ((L)->num_iters)
@@@ -901,6 -901,8 +901,8 @@@ extern void slpeel_make_loop_iterate_nt
  extern bool slpeel_can_duplicate_loop_p (const struct loop *, const_edge);
  struct loop *slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *, edge);
  extern void vect_loop_versioning (loop_vec_info, unsigned int, bool);
+ extern void vect_generate_tmps_on_preheader (loop_vec_info, tree *, tree *,
+                                            tree *, gimple_seq);
  extern void vect_do_peeling_for_loop_bound (loop_vec_info, tree *,
                                            unsigned int, bool);
  extern void vect_do_peeling_for_alignment (loop_vec_info, unsigned int, bool);
diff --combined gcc/tree-vrp.c
index fa30d1da9975c75721af5591791b58dae33f2965,15cfcb3f5913d0cd9338dd4035e4f3c835cdc3d3..03fb075193d51503e03320646260c17dbd8ca8eb
@@@ -26,6 -26,16 +26,16 @@@ along with GCC; see the file COPYING3
  #include "flags.h"
  #include "tree.h"
  #include "basic-block.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
+ #include "tree-ssa-loop-manip.h"
+ #include "tree-ssa-loop-niter.h"
+ #include "tree-ssa-loop.h"
+ #include "tree-into-ssa.h"
  #include "tree-ssa.h"
  #include "tree-pass.h"
  #include "tree-dump.h"
@@@ -40,7 -50,6 +50,7 @@@
  #include "expr.h"
  #include "optabs.h"
  #include "tree-ssa-threadedge.h"
 +#include "wide-int.h"
  
  
  
@@@ -1127,7 -1136,15 +1137,7 @@@ operand_less_p (tree val, tree val2
  {
    /* LT is folded faster than GE and others.  Inline the common case.  */
    if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST)
 -    {
 -      if (TYPE_UNSIGNED (TREE_TYPE (val)))
 -      return INT_CST_LT_UNSIGNED (val, val2);
 -      else
 -      {
 -        if (INT_CST_LT (val, val2))
 -          return 1;
 -      }
 -    }
 +    return INT_CST_LT (val, val2);
    else
      {
        tree tcmp;
@@@ -1617,8 -1634,10 +1627,8 @@@ extract_range_from_assert (value_range_
        /* Make sure to not set TREE_OVERFLOW on the final type
         conversion.  We are willingly interpreting large positive
         unsigned values as negative singed values here.  */
 -      min = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (min),
 -                                 0, false);
 -      max = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (max),
 -                                 0, false);
 +      min = force_fit_type (TREE_TYPE (var), wi::to_widest (min), 0, false);
 +      max = force_fit_type (TREE_TYPE (var), wi::to_widest (max), 0, false);
  
        /* We can transform a max, min range to an anti-range or
           vice-versa.  Use set_and_canonicalize_value_range which does
@@@ -1874,10 -1893,6 +1884,10 @@@ vrp_int_const_binop (enum tree_code cod
      /* If the singed operation wraps then int_const_binop has done
         everything we want.  */
      ;
 +  /* Signed division of -1/0 overflows and by the time it gets here
 +     returns NULL_TREE.  */
 +  else if (!res)
 +    return NULL_TREE;
    else if ((TREE_OVERFLOW (res)
            && !TREE_OVERFLOW (val1)
            && !TREE_OVERFLOW (val2))
  }
  
  
 -/* For range VR compute two double_int bitmasks.  In *MAY_BE_NONZERO
 +/* For range VR compute two wide_int bitmasks.  In *MAY_BE_NONZERO
     bitmask if some bit is unset, it means for all numbers in the range
     the bit is 0, otherwise it might be 0 or 1.  In *MUST_BE_NONZERO
     bitmask if some bit is set, it means for all numbers in the range
     the bit is 1, otherwise it might be 0 or 1.  */
  
  static bool
 -zero_nonzero_bits_from_vr (value_range_t *vr,
 -                         double_int *may_be_nonzero,
 -                         double_int *must_be_nonzero)
 +zero_nonzero_bits_from_vr (const tree expr_type,
 +                         value_range_t *vr,
 +                         wide_int *may_be_nonzero,
 +                         wide_int *must_be_nonzero)
  {
 -  *may_be_nonzero = double_int_minus_one;
 -  *must_be_nonzero = double_int_zero;
 +  *may_be_nonzero = wi::minus_one (TYPE_PRECISION (expr_type));
 +  *must_be_nonzero = wi::zero (TYPE_PRECISION (expr_type));
    if (!range_int_cst_p (vr)
        || TREE_OVERFLOW (vr->min)
        || TREE_OVERFLOW (vr->max))
  
    if (range_int_cst_singleton_p (vr))
      {
 -      *may_be_nonzero = tree_to_double_int (vr->min);
 +      *may_be_nonzero = vr->min;
        *must_be_nonzero = *may_be_nonzero;
      }
    else if (tree_int_cst_sgn (vr->min) >= 0
           || tree_int_cst_sgn (vr->max) < 0)
      {
 -      double_int dmin = tree_to_double_int (vr->min);
 -      double_int dmax = tree_to_double_int (vr->max);
 -      double_int xor_mask = dmin ^ dmax;
 -      *may_be_nonzero = dmin | dmax;
 -      *must_be_nonzero = dmin & dmax;
 -      if (xor_mask.high != 0)
 +      wide_int xor_mask = wi::bit_xor (vr->min, vr->max);
 +      *may_be_nonzero = wi::bit_or (vr->min, vr->max);
 +      *must_be_nonzero = wi::bit_and (vr->min, vr->max);
 +      if (xor_mask != 0)
        {
 -        unsigned HOST_WIDE_INT mask
 -            = ((unsigned HOST_WIDE_INT) 1
 -               << floor_log2 (xor_mask.high)) - 1;
 -        may_be_nonzero->low = ALL_ONES;
 -        may_be_nonzero->high |= mask;
 -        must_be_nonzero->low = 0;
 -        must_be_nonzero->high &= ~mask;
 -      }
 -      else if (xor_mask.low != 0)
 -      {
 -        unsigned HOST_WIDE_INT mask
 -            = ((unsigned HOST_WIDE_INT) 1
 -               << floor_log2 (xor_mask.low)) - 1;
 -        may_be_nonzero->low |= mask;
 -        must_be_nonzero->low &= ~mask;
 +        wide_int mask = wi::mask (wi::floor_log2 (xor_mask), false,
 +                                  (*may_be_nonzero).get_precision ());
 +        *may_be_nonzero = (*may_be_nonzero) | mask;
 +        *must_be_nonzero = (*must_be_nonzero).and_not (mask);
        }
      }
  
@@@ -2037,15 -2064,15 +2047,15 @@@ ranges_from_anti_range (value_range_t *
        vr0->type = VR_RANGE;
        vr0->min = vrp_val_min (type);
        vr0->max
 -      = double_int_to_tree (type,
 -                            tree_to_double_int (ar->min) - double_int_one);
 +      = wide_int_to_tree (type,
 +                          wide_int (ar->min) - 1);
      }
    if (!vrp_val_is_max (ar->max))
      {
        vr1->type = VR_RANGE;
        vr1->min
 -      = double_int_to_tree (type,
 -                            tree_to_double_int (ar->max) + double_int_one);
 +      = wide_int_to_tree (type,
 +                          wide_int (ar->max) + 1);
        vr1->max = vrp_val_max (type);
      }
    if (vr0->type == VR_UNDEFINED)
@@@ -2211,6 -2238,28 +2221,6 @@@ extract_range_from_multiplicative_op_1 
      set_value_range (vr, type, min, max, NULL);
  }
  
 -/* Some quadruple precision helpers.  */
 -static int
 -quad_int_cmp (double_int l0, double_int h0,
 -            double_int l1, double_int h1, bool uns)
 -{
 -  int c = h0.cmp (h1, uns);
 -  if (c != 0) return c;
 -  return l0.ucmp (l1);
 -}
 -
 -static void
 -quad_int_pair_sort (double_int *l0, double_int *h0,
 -                  double_int *l1, double_int *h1, bool uns)
 -{
 -  if (quad_int_cmp (*l0, *h0, *l1, *h1, uns) > 0)
 -    {
 -      double_int tmp;
 -      tmp = *l0; *l0 = *l1; *l1 = tmp;
 -      tmp = *h0; *h0 = *h1; *h1 = tmp;
 -    }
 -}
 -
  /* Extract range information from a binary operation CODE based on
     the ranges of each of its operands, *VR0 and *VR1 with resulting
     type EXPR_TYPE.  The resulting range is stored in *VR.  */
@@@ -2382,36 -2431,43 +2392,36 @@@ extract_range_from_binary_expr_1 (value
        /* If we have a PLUS_EXPR with two VR_RANGE integer constant
           ranges compute the precise range for such case if possible.  */
        if (range_int_cst_p (&vr0)
 -        && range_int_cst_p (&vr1)
 -        /* We need as many bits as the possibly unsigned inputs.  */
 -        && TYPE_PRECISION (expr_type) <= HOST_BITS_PER_DOUBLE_INT)
 -      {
 -        double_int min0 = tree_to_double_int (vr0.min);
 -        double_int max0 = tree_to_double_int (vr0.max);
 -        double_int min1 = tree_to_double_int (vr1.min);
 -        double_int max1 = tree_to_double_int (vr1.max);
 -        bool uns = TYPE_UNSIGNED (expr_type);
 -        double_int type_min
 -          = double_int::min_value (TYPE_PRECISION (expr_type), uns);
 -        double_int type_max
 -          = double_int::max_value (TYPE_PRECISION (expr_type), uns);
 -        double_int dmin, dmax;
 +        && range_int_cst_p (&vr1))
 +      {
 +        signop sgn = TYPE_SIGN (expr_type);
 +        unsigned int prec = TYPE_PRECISION (expr_type);
 +        wide_int type_min = wi::min_value (TYPE_PRECISION (expr_type), sgn);
 +        wide_int type_max = wi::max_value (TYPE_PRECISION (expr_type), sgn);
 +        wide_int wmin, wmax;
          int min_ovf = 0;
          int max_ovf = 0;
  
          if (code == PLUS_EXPR)
            {
 -            dmin = min0 + min1;
 -            dmax = max0 + max1;
 -
 -            /* Check for overflow in double_int.  */
 -            if (min1.cmp (double_int_zero, uns) != dmin.cmp (min0, uns))
 -              min_ovf = min0.cmp (dmin, uns);
 -            if (max1.cmp (double_int_zero, uns) != dmax.cmp (max0, uns))
 -              max_ovf = max0.cmp (dmax, uns);
 +            wmin = wi::add (vr0.min, vr1.min);
 +            wmax = wi::add (vr0.max, vr1.max);
 +
 +            /* Check for overflow.  */
 +            if (wi::cmp (vr1.min, 0, sgn) != wi::cmp (wmin, vr0.min, sgn))
 +              min_ovf = wi::cmp (vr0.min, wmin, sgn);
 +            if (wi::cmp (vr1.max, 0, sgn) != wi::cmp (wmax, vr0.max, sgn))
 +              max_ovf = wi::cmp (vr0.max, wmax, sgn);
            }
          else /* if (code == MINUS_EXPR) */
            {
 -            dmin = min0 - max1;
 -            dmax = max0 - min1;
 +            wmin = wi::sub (vr0.min, vr1.max);
 +            wmax = wi::sub (vr0.max, vr1.min);
  
 -            if (double_int_zero.cmp (max1, uns) != dmin.cmp (min0, uns))
 -              min_ovf = min0.cmp (max1, uns);
 -            if (double_int_zero.cmp (min1, uns) != dmax.cmp (max0, uns))
 -              max_ovf = max0.cmp (min1, uns);
 +            if (wi::cmp (0, vr1.max, sgn) != wi::cmp (wmin, vr0.min, sgn))
 +              min_ovf = wi::cmp (vr0.min, vr1.max, sgn);
 +            if (wi::cmp (0, vr1.min, sgn) != wi::cmp (wmax, vr0.max, sgn))
 +              max_ovf = wi::cmp (vr0.max, vr1.min, sgn);
            }
  
          /* For non-wrapping arithmetic look at possibly smaller
          if (!TYPE_OVERFLOW_WRAPS (expr_type))
            {
              if (vrp_val_min (expr_type))
 -              type_min = tree_to_double_int (vrp_val_min (expr_type));
 +              type_min = wide_int (vrp_val_min (expr_type));
              if (vrp_val_max (expr_type))
 -              type_max = tree_to_double_int (vrp_val_max (expr_type));
 +              type_max = wide_int (vrp_val_max (expr_type));
            }
  
          /* Check for type overflow.  */
          if (min_ovf == 0)
            {
 -            if (dmin.cmp (type_min, uns) == -1)
 +            if (wi::cmp (wmin, type_min, sgn) == -1)
                min_ovf = -1;
 -            else if (dmin.cmp (type_max, uns) == 1)
 +            else if (wi::cmp (wmin, type_max, sgn) == 1)
                min_ovf = 1;
            }
          if (max_ovf == 0)
            {
 -            if (dmax.cmp (type_min, uns) == -1)
 +            if (wi::cmp (wmax, type_min, sgn) == -1)
                max_ovf = -1;
 -            else if (dmax.cmp (type_max, uns) == 1)
 +            else if (wi::cmp (wmax, type_max, sgn) == 1)
                max_ovf = 1;
            }
  
            {
              /* If overflow wraps, truncate the values and adjust the
                 range kind and bounds appropriately.  */
 -            double_int tmin
 -              = dmin.ext (TYPE_PRECISION (expr_type), uns);
 -            double_int tmax
 -              = dmax.ext (TYPE_PRECISION (expr_type), uns);
 +            wide_int tmin = wide_int::from (wmin, prec, sgn);
 +            wide_int tmax = wide_int::from (wmax, prec, sgn);
              if (min_ovf == max_ovf)
                {
                  /* No overflow or both overflow or underflow.  The
                     range kind stays VR_RANGE.  */
 -                min = double_int_to_tree (expr_type, tmin);
 -                max = double_int_to_tree (expr_type, tmax);
 +                min = wide_int_to_tree (expr_type, tmin);
 +                max = wide_int_to_tree (expr_type, tmax);
                }
              else if (min_ovf == -1
                       && max_ovf == 1)
                  /* Min underflow or max overflow.  The range kind
                     changes to VR_ANTI_RANGE.  */
                  bool covers = false;
 -                double_int tem = tmin;
 +                wide_int tem = tmin;
                  gcc_assert ((min_ovf == -1 && max_ovf == 0)
                              || (max_ovf == 1 && min_ovf == 0));
                  type = VR_ANTI_RANGE;
 -                tmin = tmax + double_int_one;
 -                if (tmin.cmp (tmax, uns) < 0)
 +                tmin = tmax + 1;
 +                if (wi::cmp (tmin, tmax, sgn) < 0)
                    covers = true;
 -                tmax = tem + double_int_minus_one;
 -                if (tmax.cmp (tem, uns) > 0)
 +                tmax = tem - 1;
 +                if (wi::cmp (tmax, tem, sgn) > 0)
                    covers = true;
                  /* If the anti-range would cover nothing, drop to varying.
                     Likewise if the anti-range bounds are outside of the
                     types values.  */
 -                if (covers || tmin.cmp (tmax, uns) > 0)
 +                if (covers || wi::cmp (tmin, tmax, sgn) > 0)
                    {
                      set_value_range_to_varying (vr);
                      return;
                    }
 -                min = double_int_to_tree (expr_type, tmin);
 -                max = double_int_to_tree (expr_type, tmax);
 +                min = wide_int_to_tree (expr_type, tmin);
 +                max = wide_int_to_tree (expr_type, tmax);
                }
            }
          else
                      && supports_overflow_infinity (expr_type))
                    min = negative_overflow_infinity (expr_type);
                  else
 -                  min = double_int_to_tree (expr_type, type_min);
 +                  min = wide_int_to_tree (expr_type, type_min);
                }
              else if (min_ovf == 1)
                {
                      && supports_overflow_infinity (expr_type))
                    min = positive_overflow_infinity (expr_type);
                  else
 -                  min = double_int_to_tree (expr_type, type_max);
 +                  min = wide_int_to_tree (expr_type, type_max);
                }
              else
 -              min = double_int_to_tree (expr_type, dmin);
 +              min = wide_int_to_tree (expr_type, wmin);
  
              if (max_ovf == -1)
                {
                      && supports_overflow_infinity (expr_type))
                    max = negative_overflow_infinity (expr_type);
                  else
 -                  max = double_int_to_tree (expr_type, type_min);
 +                  max = wide_int_to_tree (expr_type, type_min);
                }
              else if (max_ovf == 1)
                {
                      && supports_overflow_infinity (expr_type))
                    max = positive_overflow_infinity (expr_type);
                  else
 -                  max = double_int_to_tree (expr_type, type_max);
 +                  max = wide_int_to_tree (expr_type, type_max);
                }
              else
 -              max = double_int_to_tree (expr_type, dmax);
 +              max = wide_int_to_tree (expr_type, wmax);
            }
          if (needs_overflow_infinity (expr_type)
              && supports_overflow_infinity (expr_type))
    else if (code == MULT_EXPR)
      {
        /* Fancy code so that with unsigned, [-3,-1]*[-3,-1] does not
 -       drop to varying.  */
 +       drop to varying.  This test requires 2*prec bits if both
 +       operands are signed and 2*prec + 2 bits if either is not.  */
 +
 +      signop sign = TYPE_SIGN (expr_type);
 +      unsigned int prec = TYPE_PRECISION (expr_type);
 +      unsigned int prec2 = (prec * 2) + (sign == UNSIGNED ? 2 : 0);
 +
        if (range_int_cst_p (&vr0)
          && range_int_cst_p (&vr1)
          && TYPE_OVERFLOW_WRAPS (expr_type))
        {
 -        double_int min0, max0, min1, max1, sizem1, size;
 -        double_int prod0l, prod0h, prod1l, prod1h,
 -                   prod2l, prod2h, prod3l, prod3h;
 -        bool uns0, uns1, uns;
 -
 -        sizem1 = double_int::max_value (TYPE_PRECISION (expr_type), true);
 -        size = sizem1 + double_int_one;
 -
 -        min0 = tree_to_double_int (vr0.min);
 -        max0 = tree_to_double_int (vr0.max);
 -        min1 = tree_to_double_int (vr1.min);
 -        max1 = tree_to_double_int (vr1.max);
 +        wide_int sizem1 = wi::mask (prec, false, prec2);
 +        wide_int size = sizem1 + 1;
  
 -        uns0 = TYPE_UNSIGNED (expr_type);
 -        uns1 = uns0;
 +        /* Extend the values using the sign of the result to PREC2.
 +           From here on out, everthing is just signed math no matter
 +           what the input types were.  */ 
 +        wide_int min0 = wide_int::from (vr0.min, prec2, sign);
 +        wide_int max0 = wide_int::from (vr0.max, prec2, sign);
 +        wide_int min1 = wide_int::from (vr1.min, prec2, sign);
 +        wide_int max1 = wide_int::from (vr1.max, prec2, sign);
  
          /* Canonicalize the intervals.  */
 -        if (TYPE_UNSIGNED (expr_type))
 +        if (sign == UNSIGNED)
            {
 -            double_int min2 = size - min0;
 -            if (!min2.is_zero () && min2.cmp (max0, true) < 0)
 +            if (wi::ltu_p (size, min0 + max0))
                {
 -                min0 = -min2;
 +                min0 -= size;
                  max0 -= size;
 -                uns0 = false;
                }
  
 -            min2 = size - min1;
 -            if (!min2.is_zero () && min2.cmp (max1, true) < 0)
 +            if (wi::ltu_p (size, min1 + max1))
                {
 -                min1 = -min2;
 +                min1 -= size;
                  max1 -= size;
 -                uns1 = false;
                }
            }
 -        uns = uns0 & uns1;
  
 -        bool overflow;
 -        prod0l = min0.wide_mul_with_sign (min1, true, &prod0h, &overflow);
 -        if (!uns0 && min0.is_negative ())
 -          prod0h -= min1;
 -        if (!uns1 && min1.is_negative ())
 -          prod0h -= min0;
 -
 -        prod1l = min0.wide_mul_with_sign (max1, true, &prod1h, &overflow);
 -        if (!uns0 && min0.is_negative ())
 -          prod1h -= max1;
 -        if (!uns1 && max1.is_negative ())
 -          prod1h -= min0;
 -
 -        prod2l = max0.wide_mul_with_sign (min1, true, &prod2h, &overflow);
 -        if (!uns0 && max0.is_negative ())
 -          prod2h -= min1;
 -        if (!uns1 && min1.is_negative ())
 -          prod2h -= max0;
 -
 -        prod3l = max0.wide_mul_with_sign (max1, true, &prod3h, &overflow);
 -        if (!uns0 && max0.is_negative ())
 -          prod3h -= max1;
 -        if (!uns1 && max1.is_negative ())
 -          prod3h -= max0;
 -
 -        /* Sort the 4 products.  */
 -        quad_int_pair_sort (&prod0l, &prod0h, &prod3l, &prod3h, uns);
 -        quad_int_pair_sort (&prod1l, &prod1h, &prod2l, &prod2h, uns);
 -        quad_int_pair_sort (&prod0l, &prod0h, &prod1l, &prod1h, uns);
 -        quad_int_pair_sort (&prod2l, &prod2h, &prod3l, &prod3h, uns);
 -
 -        /* Max - min.  */
 -        if (prod0l.is_zero ())
 +        wide_int prod0 = min0 * min1;
 +        wide_int prod1 = min0 * max1;
 +        wide_int prod2 = max0 * min1;
 +        wide_int prod3 = max0 * max1;
 +
 +        /* Sort the 4 products so that min is in prod0 and max is in
 +           prod3.  */
 +        /* min0min1 > max0max1 */
 +        if (wi::gts_p (prod0, prod3))
            {
 -            prod1l = double_int_zero;
 -            prod1h = -prod0h;
 +            wide_int tmp = prod3;
 +            prod3 = prod0;
 +            prod0 = tmp;
            }
 -        else
 +
 +        /* min0max1 > max0min1 */
 +        if (wi::gts_p (prod1, prod2))
 +          {
 +            wide_int tmp = prod2;
 +            prod2 = prod1;
 +            prod1 = tmp;
 +          }
 +
 +        if (wi::gts_p (prod0, prod1))
 +          {
 +            wide_int tmp = prod1;
 +            prod1 = prod0;
 +            prod0 = tmp;
 +          }
 +
 +        if (wi::gts_p (prod2, prod3))
            {
 -            prod1l = -prod0l;
 -            prod1h = ~prod0h;
 +            wide_int tmp = prod3;
 +            prod3 = prod2;
 +            prod2 = tmp;
            }
 -        prod2l = prod3l + prod1l;
 -        prod2h = prod3h + prod1h;
 -        if (prod2l.ult (prod3l))
 -          prod2h += double_int_one; /* carry */
  
 -        if (!prod2h.is_zero ()
 -            || prod2l.cmp (sizem1, true) >= 0)
 +        /* diff = max - min.  */
 +        prod2 = prod3 - prod0;
 +        if (wi::geu_p (prod2, sizem1))
            {
              /* the range covers all values.  */
              set_value_range_to_varying (vr);
  
          /* The following should handle the wrapping and selecting
             VR_ANTI_RANGE for us.  */
 -        min = double_int_to_tree (expr_type, prod0l);
 -        max = double_int_to_tree (expr_type, prod3l);
 +        min = wide_int_to_tree (expr_type, prod0);
 +        max = wide_int_to_tree (expr_type, prod3);
          set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
          return;
        }
              bool saved_flag_wrapv;
              value_range_t vr1p = VR_INITIALIZER;
              vr1p.type = VR_RANGE;
 -            vr1p.min
 -              = double_int_to_tree (expr_type,
 -                                    double_int_one
 -                                    .llshift (TREE_INT_CST_LOW (vr1.min),
 -                                              TYPE_PRECISION (expr_type)));
 +            vr1p.min = (wide_int_to_tree
 +                        (expr_type,
 +                         wi::set_bit_in_zero (tree_to_shwi (vr1.min),
 +                                              TYPE_PRECISION (expr_type))));
              vr1p.max = vr1p.min;
              /* We have to use a wrapping multiply though as signed overflow
                 on lshifts is implementation defined in C89.  */
              int prec = TYPE_PRECISION (expr_type);
              int overflow_pos = prec;
              int bound_shift;
 -            double_int bound, complement, low_bound, high_bound;
 +            wide_int low_bound, high_bound;
              bool uns = TYPE_UNSIGNED (expr_type);
              bool in_bounds = false;
  
              if (!uns)
                overflow_pos -= 1;
  
 -            bound_shift = overflow_pos - TREE_INT_CST_LOW (vr1.max);
 -            /* If bound_shift == HOST_BITS_PER_DOUBLE_INT, the llshift can
 +            bound_shift = overflow_pos - tree_to_shwi (vr1.max);
 +            /* If bound_shift == HOST_BITS_PER_WIDE_INT, the llshift can
                 overflow.  However, for that to happen, vr1.max needs to be
                 zero, which means vr1 is a singleton range of zero, which
                 means it should be handled by the previous LSHIFT_EXPR
                 if-clause.  */
 -            bound = double_int_one.llshift (bound_shift, prec);
 -            complement = ~(bound - double_int_one);
 +            wide_int bound = wi::set_bit_in_zero (bound_shift, prec);
 +            wide_int complement = ~(bound - 1);
  
              if (uns)
                {
 -                low_bound = bound.zext (prec);
 -                high_bound = complement.zext (prec);
 -                if (tree_to_double_int (vr0.max).ult (low_bound))
 +                low_bound = bound;
 +                high_bound = complement;
 +                if (wi::ltu_p (vr0.max, low_bound))
                    {
                      /* [5, 6] << [1, 2] == [10, 24].  */
                      /* We're shifting out only zeroes, the value increases
                         monotonically.  */
                      in_bounds = true;
                    }
 -                else if (high_bound.ult (tree_to_double_int (vr0.min)))
 +                else if (wi::ltu_p (high_bound, vr0.min))
                    {
                      /* [0xffffff00, 0xffffffff] << [1, 2]
                         == [0xfffffc00, 0xfffffffe].  */
              else
                {
                  /* [-1, 1] << [1, 2] == [-4, 4].  */
 -                low_bound = complement.sext (prec);
 +                low_bound = complement;
                  high_bound = bound;
 -                if (tree_to_double_int (vr0.max).slt (high_bound)
 -                    && low_bound.slt (tree_to_double_int (vr0.min)))
 +                if (wi::lts_p (vr0.max, high_bound)
 +                    && wi::lts_p (low_bound, vr0.min))
                    {
                      /* For non-negative numbers, we're shifting out only
                         zeroes, the value increases monotonically.
        max = fold_unary_to_constant (ABS_EXPR, expr_type, vr1.min);
        if (tree_int_cst_lt (max, vr1.max))
        max = vr1.max;
 -      max = int_const_binop (MINUS_EXPR, max, integer_one_node);
 +      max = int_const_binop (MINUS_EXPR, max, build_int_cst (TREE_TYPE (max), 1));
        /* If the dividend is non-negative the modulus will be
         non-negative as well.  */
        if (TYPE_UNSIGNED (expr_type)
    else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR)
      {
        bool int_cst_range0, int_cst_range1;
 -      double_int may_be_nonzero0, may_be_nonzero1;
 -      double_int must_be_nonzero0, must_be_nonzero1;
 +      wide_int may_be_nonzero0, may_be_nonzero1;
 +      wide_int must_be_nonzero0, must_be_nonzero1;
  
 -      int_cst_range0 = zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0,
 +      int_cst_range0 = zero_nonzero_bits_from_vr (expr_type, &vr0,
 +                                                &may_be_nonzero0,
                                                  &must_be_nonzero0);
 -      int_cst_range1 = zero_nonzero_bits_from_vr (&vr1, &may_be_nonzero1,
 +      int_cst_range1 = zero_nonzero_bits_from_vr (expr_type, &vr1,
 +                                                &may_be_nonzero1,
                                                  &must_be_nonzero1);
  
        type = VR_RANGE;
        if (code == BIT_AND_EXPR)
        {
 -        double_int dmax;
 -        min = double_int_to_tree (expr_type,
 -                                  must_be_nonzero0 & must_be_nonzero1);
 -        dmax = may_be_nonzero0 & may_be_nonzero1;
 +        min = wide_int_to_tree (expr_type,
 +                                must_be_nonzero0 & must_be_nonzero1);
 +        wide_int wmax = may_be_nonzero0 & may_be_nonzero1;
          /* If both input ranges contain only negative values we can
             truncate the result range maximum to the minimum of the
             input range maxima.  */
              && tree_int_cst_sgn (vr0.max) < 0
              && tree_int_cst_sgn (vr1.max) < 0)
            {
 -            dmax = dmax.min (tree_to_double_int (vr0.max),
 -                                   TYPE_UNSIGNED (expr_type));
 -            dmax = dmax.min (tree_to_double_int (vr1.max),
 -                                   TYPE_UNSIGNED (expr_type));
 +            wmax = wi::min (wmax, vr0.max, TYPE_SIGN (expr_type));
 +            wmax = wi::min (wmax, vr1.max, TYPE_SIGN (expr_type));
            }
          /* If either input range contains only non-negative values
             we can truncate the result range maximum to the respective
             maximum of the input range.  */
          if (int_cst_range0 && tree_int_cst_sgn (vr0.min) >= 0)
 -          dmax = dmax.min (tree_to_double_int (vr0.max),
 -                                 TYPE_UNSIGNED (expr_type));
 +          wmax = wi::min (wmax, vr0.max, TYPE_SIGN (expr_type));
          if (int_cst_range1 && tree_int_cst_sgn (vr1.min) >= 0)
 -          dmax = dmax.min (tree_to_double_int (vr1.max),
 -                                 TYPE_UNSIGNED (expr_type));
 -        max = double_int_to_tree (expr_type, dmax);
 +          wmax = wi::min (wmax, vr1.max, TYPE_SIGN (expr_type));
 +        max = wide_int_to_tree (expr_type, wmax);
        }
        else if (code == BIT_IOR_EXPR)
        {
 -        double_int dmin;
 -        max = double_int_to_tree (expr_type,
 -                                  may_be_nonzero0 | may_be_nonzero1);
 -        dmin = must_be_nonzero0 | must_be_nonzero1;
 +        max = wide_int_to_tree (expr_type,
 +                                may_be_nonzero0 | may_be_nonzero1);
 +        wide_int wmin = must_be_nonzero0 | must_be_nonzero1;
          /* If the input ranges contain only positive values we can
             truncate the minimum of the result range to the maximum
             of the input range minima.  */
              && tree_int_cst_sgn (vr0.min) >= 0
              && tree_int_cst_sgn (vr1.min) >= 0)
            {
 -            dmin = dmin.max (tree_to_double_int (vr0.min),
 -                             TYPE_UNSIGNED (expr_type));
 -            dmin = dmin.max (tree_to_double_int (vr1.min),
 -                             TYPE_UNSIGNED (expr_type));
 +            wmin = wi::max (wmin, vr0.min, TYPE_SIGN (expr_type));
 +            wmin = wi::max (wmin, vr1.min, TYPE_SIGN (expr_type));
            }
          /* If either input range contains only negative values
             we can truncate the minimum of the result range to the
             respective minimum range.  */
          if (int_cst_range0 && tree_int_cst_sgn (vr0.max) < 0)
 -          dmin = dmin.max (tree_to_double_int (vr0.min),
 -                           TYPE_UNSIGNED (expr_type));
 +          wmin = wi::max (wmin, vr0.min, TYPE_SIGN (expr_type));
          if (int_cst_range1 && tree_int_cst_sgn (vr1.max) < 0)
 -          dmin = dmin.max (tree_to_double_int (vr1.min),
 -                           TYPE_UNSIGNED (expr_type));
 -        min = double_int_to_tree (expr_type, dmin);
 +          wmin = wi::max (wmin, vr1.min, TYPE_SIGN (expr_type));
 +        min = wide_int_to_tree (expr_type, wmin);
        }
        else if (code == BIT_XOR_EXPR)
        {
 -        double_int result_zero_bits, result_one_bits;
 -        result_zero_bits = (must_be_nonzero0 & must_be_nonzero1)
 -                           | ~(may_be_nonzero0 | may_be_nonzero1);
 -        result_one_bits = must_be_nonzero0.and_not (may_be_nonzero1)
 -                          | must_be_nonzero1.and_not (may_be_nonzero0);
 -        max = double_int_to_tree (expr_type, ~result_zero_bits);
 -        min = double_int_to_tree (expr_type, result_one_bits);
 +        wide_int result_zero_bits = ((must_be_nonzero0 & must_be_nonzero1)
 +                                     | ~(may_be_nonzero0 | may_be_nonzero1));
 +        wide_int result_one_bits
 +          = (must_be_nonzero0.and_not (may_be_nonzero1)
 +             | must_be_nonzero1.and_not (may_be_nonzero0));
 +        max = wide_int_to_tree (expr_type, ~result_zero_bits);
 +        min = wide_int_to_tree (expr_type, result_one_bits);
          /* If the range has all positive or all negative values the
             result is better than VARYING.  */
          if (tree_int_cst_sgn (min) < 0
@@@ -3227,13 -3307,15 +3237,13 @@@ extract_range_from_unary_expr_1 (value_
          if (is_overflow_infinity (vr0.min))
            new_min = negative_overflow_infinity (outer_type);
          else
 -          new_min = force_fit_type_double (outer_type,
 -                                           tree_to_double_int (vr0.min),
 -                                           0, false);
 +          new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
 +                                    0, false);
          if (is_overflow_infinity (vr0.max))
            new_max = positive_overflow_infinity (outer_type);
          else
 -          new_max = force_fit_type_double (outer_type,
 -                                           tree_to_double_int (vr0.max),
 -                                           0, false);
 +          new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
 +                                    0, false);
          set_and_canonicalize_value_range (vr, vr0.type,
                                            new_min, new_max, NULL);
          return;
  
                  min = (vr0.min != type_min_value
                         ? int_const_binop (PLUS_EXPR, type_min_value,
 -                                          integer_one_node)
 +                                          build_int_cst (TREE_TYPE (type_min_value), 1))
                         : type_min_value);
                }
              else
@@@ -3806,28 -3888,30 +3816,28 @@@ adjust_range_with_scev (value_range_t *
        && (TREE_CODE (init) != SSA_NAME
          || get_value_range (init)->type == VR_RANGE))
      {
 -      double_int nit;
 +      widest_int nit;
  
        /* We are only entering here for loop header PHI nodes, so using
         the number of latch executions is the correct thing to use.  */
        if (max_loop_iterations (loop, &nit))
        {
          value_range_t maxvr = VR_INITIALIZER;
 -        double_int dtmp;
 -        bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (step));
 -        bool overflow = false;
 -
 -        dtmp = tree_to_double_int (step)
 -               .mul_with_sign (nit, unsigned_p, &overflow);
 +        signop sgn = TYPE_SIGN (TREE_TYPE (step));
 +        bool overflow;
 +        
 +        wide_int wtmp = wi::mul (wi::to_widest (step), nit, sgn, &overflow);
          /* If the multiplication overflowed we can't do a meaningful
             adjustment.  Likewise if the result doesn't fit in the type
             of the induction variable.  For a signed type we have to
             check whether the result has the expected signedness which
             is that of the step as number of iterations is unsigned.  */
          if (!overflow
 -            && double_int_fits_to_tree_p (TREE_TYPE (init), dtmp)
 -            && (unsigned_p
 -                || ((dtmp.high ^ TREE_INT_CST_HIGH (step)) >= 0)))
 +            && wi::fits_to_tree_p (wtmp, TREE_TYPE (init))
 +            && (sgn == UNSIGNED
 +                || wi::gts_p (wtmp, 0) == wi::gts_p (step, 0)))
            {
 -            tem = double_int_to_tree (TREE_TYPE (init), dtmp);
 +            tem = wide_int_to_tree (TREE_TYPE (init), wtmp);
              extract_range_from_binary_expr (&maxvr, PLUS_EXPR,
                                              TREE_TYPE (init), init, tem);
              /* Likewise if the addition did.  */
@@@ -4432,7 -4516,7 +4442,7 @@@ infer_nonnull_range (gimple stmt, tree 
          /* Now see if op appears in the nonnull list.  */
          for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
            {
 -            int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
 +            int idx = tree_to_shwi (TREE_VALUE (t)) - 1;
              tree arg = gimple_call_arg (stmt, idx);
              if (op == arg)
                return true;
@@@ -4588,7 -4672,8 +4598,7 @@@ register_new_assert_for (tree name, tre
       machinery.  */
    if (TREE_CODE (val) == INTEGER_CST
        && TREE_OVERFLOW (val))
 -    val = build_int_cst_wide (TREE_TYPE (val),
 -                            TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val));
 +    val = wide_int_to_tree (TREE_TYPE (val), val);
  
    /* The new assertion A will be inserted at BB or E.  We need to
       determine if the new location is dominated by a previously
@@@ -4741,23 -4826,23 +4751,23 @@@ extract_code_and_val_from_cond_with_op
     (to transform signed values into unsigned) and at the end xor
     SGNBIT back.  */
  
 -static double_int
 -masked_increment (double_int val, double_int mask, double_int sgnbit,
 +static wide_int
 +masked_increment (wide_int val, wide_int mask, wide_int sgnbit,
                  unsigned int prec)
  {
 -  double_int bit = double_int_one, res;
 +  wide_int bit = wi::one (prec), res;
    unsigned int i;
  
    val ^= sgnbit;
    for (i = 0; i < prec; i++, bit += bit)
      {
        res = mask;
 -      if ((res & bit).is_zero ())
 +      if ((res & bit) == 0)
        continue;
 -      res = bit - double_int_one;
 +      res = bit - 1;
        res = (val + bit).and_not (res);
        res &= mask;
 -      if (res.ugt (val))
 +      if (wi::gtu_p (res, val))
        return res ^ sgnbit;
      }
    return val ^ sgnbit;
@@@ -4932,8 -5017,8 +4942,8 @@@ register_edge_assert_for_2 (tree name, 
        gimple def_stmt = SSA_NAME_DEF_STMT (name);
        tree name2 = NULL_TREE, names[2], cst2 = NULL_TREE;
        tree val2 = NULL_TREE;
 -      double_int mask = double_int_zero;
        unsigned int prec = TYPE_PRECISION (TREE_TYPE (val));
 +      wide_int mask = wi::zero (prec);
        unsigned int nprec = prec;
        enum tree_code rhs_code = ERROR_MARK;
  
          name2 = gimple_assign_rhs1 (def_stmt);
          cst2 = gimple_assign_rhs2 (def_stmt);
          if (TREE_CODE (name2) == SSA_NAME
 -            && host_integerp (cst2, 1)
 +            && tree_fits_uhwi_p (cst2)
              && INTEGRAL_TYPE_P (TREE_TYPE (name2))
 -            && IN_RANGE (tree_low_cst (cst2, 1), 1, prec - 1)
 -            && prec <= HOST_BITS_PER_DOUBLE_INT
 +            && IN_RANGE (tree_to_uhwi (cst2), 1, prec - 1)
              && prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val)))
              && live_on_edge (e, name2)
              && !has_single_use (name2))
            {
 -            mask = double_int::mask (tree_low_cst (cst2, 1));
 +            mask = wi::mask (tree_to_uhwi (cst2), false, prec);
              val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2);
            }
        }
                  val2 = fold_convert (type, val2);
                }
              tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), tmp, val2);
 -            new_val = double_int_to_tree (TREE_TYPE (tmp), mask);
 +            new_val = wide_int_to_tree (TREE_TYPE (tmp), mask);
              new_comp_code = comp_code == EQ_EXPR ? LE_EXPR : GT_EXPR;
            }
          else if (comp_code == LT_EXPR || comp_code == GE_EXPR)
            {
 -            double_int minval
 -              = double_int::min_value (prec, TYPE_UNSIGNED (TREE_TYPE (val)));
 +            wide_int minval
 +              = wi::min_value (prec, TYPE_SIGN (TREE_TYPE (val)));
              new_val = val2;
 -            if (minval == tree_to_double_int (new_val))
 +            if (minval == wide_int (new_val))
                new_val = NULL_TREE;
            }
          else
            {
 -            double_int maxval
 -              = double_int::max_value (prec, TYPE_UNSIGNED (TREE_TYPE (val)));
 -            mask |= tree_to_double_int (val2);
 +            wide_int maxval
 +              = wi::max_value (prec, TYPE_SIGN (TREE_TYPE (val)));
 +            mask |= wide_int (val2);
              if (mask == maxval)
                new_val = NULL_TREE;
              else
 -              new_val = double_int_to_tree (TREE_TYPE (val2), mask);
 +              new_val = wide_int_to_tree (TREE_TYPE (val2), mask);
            }
  
          if (new_val)
              && INTEGRAL_TYPE_P (TREE_TYPE (name2))
              && TREE_CODE (cst2) == INTEGER_CST
              && !integer_zerop (cst2)
 -            && nprec <= HOST_BITS_PER_DOUBLE_INT
              && (nprec > 1
                  || TYPE_UNSIGNED (TREE_TYPE (val))))
            {
        }
        if (names[0] || names[1])
        {
 -        double_int minv, maxv = double_int_zero, valv, cst2v;
 -        double_int tem, sgnbit;
 +        wide_int minv, maxv, valv, cst2v;
 +        wide_int tem, sgnbit;
          bool valid_p = false, valn = false, cst2n = false;
          enum tree_code ccode = comp_code;
  
 -        valv = tree_to_double_int (val).zext (nprec);
 -        cst2v = tree_to_double_int (cst2).zext (nprec);
 -        if (!TYPE_UNSIGNED (TREE_TYPE (val)))
 +        valv = wide_int::from (val, nprec, UNSIGNED);
 +        cst2v = wide_int::from (cst2, nprec, UNSIGNED);
 +        if (TYPE_SIGN (TREE_TYPE (val)) == SIGNED)
            {
 -            valn = valv.sext (nprec).is_negative ();
 -            cst2n = cst2v.sext (nprec).is_negative ();
 +            valn = wi::neg_p (wi::sext (valv, nprec));
 +            cst2n = wi::neg_p (wi::sext (cst2v, nprec));
            }
          /* If CST2 doesn't have most significant bit set,
             but VAL is negative, we have comparison like
          if (!cst2n && valn)
            ccode = ERROR_MARK;
          if (cst2n)
 -          sgnbit = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
 +          sgnbit = wi::set_bit_in_zero (nprec - 1, nprec);
          else
 -          sgnbit = double_int_zero;
 +          sgnbit = wi::zero (nprec);
          minv = valv & cst2v;
          switch (ccode)
            {
                 have folded the comparison into false) and
                 maximum unsigned value is VAL | ~CST2.  */
              maxv = valv | ~cst2v;
 -            maxv = maxv.zext (nprec);
 +            maxv = wi::zext (maxv, nprec);
              valid_p = true;
              break;
 +
            case NE_EXPR:
              tem = valv | ~cst2v;
 -            tem = tem.zext (nprec);
 +            tem = wi::zext (tem, nprec);
              /* If VAL is 0, handle (X & CST2) != 0 as (X & CST2) > 0U.  */
 -            if (valv.is_zero ())
 +            if (valv == 0)
                {
                  cst2n = false;
 -                sgnbit = double_int_zero;
 +                sgnbit = wi::zero (nprec);
                  goto gt_expr;
                }
              /* If (VAL | ~CST2) is all ones, handle it as
                 (X & CST2) < VAL.  */
 -            if (tem == double_int::mask (nprec))
 +            if (tem == -1)
                {
                  cst2n = false;
                  valn = false;
 -                sgnbit = double_int_zero;
 +                sgnbit = wi::zero (nprec);
                  goto lt_expr;
                }
 -            if (!cst2n
 -                && cst2v.sext (nprec).is_negative ())
 -              sgnbit
 -                = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
 -            if (!sgnbit.is_zero ())
 +            if (!cst2n && wi::neg_p (wi::sext (cst2v, nprec)))
 +              sgnbit = wi::set_bit_in_zero (nprec - 1, nprec);
 +            if (sgnbit != 0)
                {
                  if (valv == sgnbit)
                    {
                      valn = true;
                      goto gt_expr;
                    }
 -                if (tem == double_int::mask (nprec - 1))
 +                if (tem == wi::mask (nprec - 1, false, nprec))
                    {
                      cst2n = true;
                      goto lt_expr;
                    }
                  if (!cst2n)
 -                  sgnbit = double_int_zero;
 +                  sgnbit = wi::zero (nprec);
                }
              break;
 +
            case GE_EXPR:
              /* Minimum unsigned value for >= if (VAL & CST2) == VAL
                 is VAL and maximum unsigned value is ~0.  For signed
                  if (minv == valv)
                    break;
                }
 -            maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
 +            maxv = wi::mask (nprec - (cst2n ? 1 : 0), false, nprec);
              valid_p = true;
              break;
 +
            case GT_EXPR:
            gt_expr:
              /* Find out smallest MINV where MINV > VAL
              minv = masked_increment (valv, cst2v, sgnbit, nprec);
              if (minv == valv)
                break;
 -            maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
 +            maxv = wi::mask (nprec - (cst2n ? 1 : 0), false, nprec);
              valid_p = true;
              break;
 +
            case LE_EXPR:
              /* Minimum unsigned value for <= is 0 and maximum
                 unsigned value is VAL | ~CST2 if (VAL & CST2) == VAL.
                  maxv = masked_increment (valv, cst2v, sgnbit, nprec);
                  if (maxv == valv)
                    break;
 -                maxv -= double_int_one;
 +                maxv -= 1;
                }
              maxv |= ~cst2v;
 -            maxv = maxv.zext (nprec);
 +            maxv = wi::zext (maxv, nprec);
              minv = sgnbit;
              valid_p = true;
              break;
 +
            case LT_EXPR:
            lt_expr:
              /* Minimum unsigned value for < is 0 and maximum
                  if (maxv == valv)
                    break;
                }
 -            maxv -= double_int_one;
 +            maxv -= 1;
              maxv |= ~cst2v;
 -            maxv = maxv.zext (nprec);
 +            maxv = wi::zext (maxv, nprec);
              minv = sgnbit;
              valid_p = true;
              break;
 +
            default:
              break;
            }
          if (valid_p
 -            && (maxv - minv).zext (nprec) != double_int::mask (nprec))
 +            && wi::zext (maxv - minv, nprec) != wi::minus_one (nprec))
            {
              tree tmp, new_val, type;
              int i;
              for (i = 0; i < 2; i++)
                if (names[i])
                  {
 -                  double_int maxv2 = maxv;
 +                  wide_int maxv2 = maxv;
                    tmp = names[i];
                    type = TREE_TYPE (names[i]);
                    if (!TYPE_UNSIGNED (type))
                        type = build_nonstandard_integer_type (nprec, 1);
                        tmp = build1 (NOP_EXPR, type, names[i]);
                      }
 -                  if (!minv.is_zero ())
 +                  if (minv != 0)
                      {
                        tmp = build2 (PLUS_EXPR, type, tmp,
 -                                    double_int_to_tree (type, -minv));
 +                                    wide_int_to_tree (type, -minv));
                        maxv2 = maxv - minv;
                      }
 -                  new_val = double_int_to_tree (type, maxv2);
 +                  new_val = wide_int_to_tree (type, maxv2);
  
                    if (dump_file)
                      {
@@@ -6143,8 -6226,7 +6153,8 @@@ check_array_ref (location_t location, t
      }
  
    low_bound = array_ref_low_bound (ref);
 -  up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, integer_one_node);
 +  up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, 
 +                               build_int_cst (TREE_TYPE (up_bound), 1));
  
    if (TREE_CODE (low_sub) == SSA_NAME)
      {
@@@ -6241,7 -6323,7 +6251,7 @@@ search_for_addr_array (tree t, location
      {
        tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
        tree low_bound, up_bound, el_sz;
 -      double_int idx;
 +      offset_int idx;
        if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
          || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
          || !TYPE_DOMAIN (TREE_TYPE (tem)))
        return;
  
        idx = mem_ref_offset (t);
 -      idx = idx.sdiv (tree_to_double_int (el_sz), TRUNC_DIV_EXPR);
 -      if (idx.slt (double_int_zero))
 +      idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
 +      if (wi::lts_p (idx, 0))
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
                      "array subscript is below array bounds");
          TREE_NO_WARNING (t) = 1;
        }
 -      else if (idx.sgt (tree_to_double_int (up_bound)
 -                      - tree_to_double_int (low_bound)
 -                      + double_int_one))
 +      else if (wi::gts_p (idx, (wi::to_offset (up_bound)
 +                              - wi::to_offset (low_bound) + 1)))
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
@@@ -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
@@@ -6405,12 -6569,16 +6496,16 @@@ remove_range_assertions (void
  {
    basic_block bb;
    gimple_stmt_iterator si;
+   /* 1 if looking at ASSERT_EXPRs immediately at the beginning of
+      a basic block preceeded by GIMPLE_COND branching to it and
+      __builtin_trap, -1 if not yet checked, 0 otherwise.  */
+   int is_unreachable;
  
    /* Note that the BSI iterator bump happens at the bottom of the
       loop and no bump is necessary if we're removing the statement
       referenced by the current BSI.  */
    FOR_EACH_BB (bb)
-     for (si = gsi_start_bb (bb); !gsi_end_p (si);)
+     for (si = gsi_after_labels (bb), is_unreachable = -1; !gsi_end_p (si);)
        {
        gimple stmt = gsi_stmt (si);
        gimple use_stmt;
        if (is_gimple_assign (stmt)
            && gimple_assign_rhs_code (stmt) == ASSERT_EXPR)
          {
+           tree lhs = gimple_assign_lhs (stmt);
            tree rhs = gimple_assign_rhs1 (stmt);
            tree var;
            tree cond = fold (ASSERT_EXPR_COND (rhs));
  
            gcc_assert (cond != boolean_false_node);
  
-           /* Propagate the RHS into every use of the LHS.  */
            var = ASSERT_EXPR_VAR (rhs);
-           FOR_EACH_IMM_USE_STMT (use_stmt, iter,
-                                  gimple_assign_lhs (stmt))
+           gcc_assert (TREE_CODE (var) == SSA_NAME);
+           if (!POINTER_TYPE_P (TREE_TYPE (lhs))
+               && SSA_NAME_RANGE_INFO (lhs))
+             {
+               if (is_unreachable == -1)
+                 {
+                   is_unreachable = 0;
+                   if (single_pred_p (bb)
+                       && assert_unreachable_fallthru_edge_p
+                                                   (single_pred_edge (bb)))
+                     is_unreachable = 1;
+                 }
+               /* Handle
+                  if (x_7 >= 10 && x_7 < 20)
+                    __builtin_unreachable ();
+                  x_8 = ASSERT_EXPR <x_7, ...>;
+                  if the only uses of x_7 are in the ASSERT_EXPR and
+                  in the condition.  In that case, we can copy the
+                  range info from x_8 computed in this pass also
+                  for x_7.  */
+               if (is_unreachable
+                   && all_imm_uses_in_stmt_or_feed_cond (var, stmt,
+                                                         single_pred (bb)))
+                 {
+                   set_range_info (var, SSA_NAME_RANGE_INFO (lhs)->min,
+                                   SSA_NAME_RANGE_INFO (lhs)->max);
+                   maybe_set_nonzero_bits (bb, var);
+                 }
+             }
+           /* Propagate the RHS into every use of the LHS.  */
+           FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
              FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
-               {
-                 SET_USE (use_p, var);
-                 gcc_assert (TREE_CODE (var) == SSA_NAME);
-               }
+               SET_USE (use_p, var);
  
            /* And finally, remove the copy, it is not needed.  */
            gsi_remove (&si, true);
            release_defs (stmt);
          }
        else
-         gsi_next (&si);
+         {
+           gsi_next (&si);
+           is_unreachable = 0;
+         }
        }
  }
  
@@@ -7468,11 -7667,9 +7594,11 @@@ union_ranges (enum value_range_type *vr
                  && vrp_val_is_max (vr1max))
                {
                  tree min = int_const_binop (PLUS_EXPR,
 -                                            *vr0max, integer_one_node);
 +                                            *vr0max, 
 +                                            build_int_cst (TREE_TYPE (*vr0max), 1));
                  tree max = int_const_binop (MINUS_EXPR,
 -                                            vr1min, integer_one_node);
 +                                            vr1min, 
 +                                            build_int_cst (TREE_TYPE (vr1min), 1));
                  if (!operand_less_p (max, min))
                    {
                      *vr0type = VR_ANTI_RANGE;
                  && vrp_val_is_max (*vr0max))
                {
                  tree min = int_const_binop (PLUS_EXPR,
 -                                            vr1max, integer_one_node);
 +                                            vr1max,
 +                                            build_int_cst (TREE_TYPE (vr1max), 1));
                  tree max = int_const_binop (MINUS_EXPR,
 -                                            *vr0min, integer_one_node);
 +                                            *vr0min,
 +                                            build_int_cst (TREE_TYPE (*vr0min), 1));
                  if (!operand_less_p (max, min))
                    {
                      *vr0type = VR_ANTI_RANGE;
        {
          /* Arbitrarily choose the right or left gap.  */
          if (!mineq && TREE_CODE (vr1min) == INTEGER_CST)
 -          *vr0max = int_const_binop (MINUS_EXPR, vr1min, integer_one_node);
 +          *vr0max = int_const_binop (MINUS_EXPR, vr1min, 
 +                                     build_int_cst (TREE_TYPE (vr1min), 1));
          else if (!maxeq && TREE_CODE (vr1max) == INTEGER_CST)
 -          *vr0min = int_const_binop (PLUS_EXPR, vr1max, integer_one_node);
 +          *vr0min = int_const_binop (PLUS_EXPR, vr1max,
 +                                     build_int_cst (TREE_TYPE (vr1max), 1));
          else
            goto give_up;
        }
          *vr0type = VR_ANTI_RANGE;
          if (!mineq && TREE_CODE (*vr0min) == INTEGER_CST)
            {
 -            *vr0max = int_const_binop (MINUS_EXPR, *vr0min, integer_one_node);
 +            *vr0max = int_const_binop (MINUS_EXPR, *vr0min,
 +                                       build_int_cst (TREE_TYPE (*vr0min), 1));
              *vr0min = vr1min;
            }
          else if (!maxeq && TREE_CODE (*vr0max) == INTEGER_CST)
            {
 -            *vr0min = int_const_binop (PLUS_EXPR, *vr0max, integer_one_node);
 +            *vr0min = int_const_binop (PLUS_EXPR, *vr0max,
 +                                       build_int_cst (TREE_TYPE (*vr0max), 1));
              *vr0max = vr1max;
            }
          else
               && vr1type == VR_RANGE)
        {
          if (TREE_CODE (vr1min) == INTEGER_CST)
 -          *vr0max = int_const_binop (MINUS_EXPR, vr1min, integer_one_node);
 +          *vr0max = int_const_binop (MINUS_EXPR, vr1min, 
 +                                     build_int_cst (TREE_TYPE (vr1min), 1));
          else
            goto give_up;
        }
          if (TREE_CODE (*vr0max) == INTEGER_CST)
            {
              *vr0type = vr1type;
 -            *vr0min = int_const_binop (PLUS_EXPR, *vr0max, integer_one_node);
 +            *vr0min = int_const_binop (PLUS_EXPR, *vr0max,
 +                                       build_int_cst (TREE_TYPE (*vr0max), 1));
              *vr0max = vr1max;
            }
          else
               && vr1type == VR_RANGE)
        {
          if (TREE_CODE (vr1max) == INTEGER_CST)
 -          *vr0min = int_const_binop (PLUS_EXPR, vr1max, integer_one_node);
 +          *vr0min = int_const_binop (PLUS_EXPR, vr1max,
 +                                     build_int_cst (TREE_TYPE (vr1max), 1));
          else
            goto give_up;
        }
            {
              *vr0type = vr1type;
              *vr0min = vr1min;
 -            *vr0max = int_const_binop (MINUS_EXPR, *vr0min, integer_one_node);
 +            *vr0max = int_const_binop (MINUS_EXPR, *vr0min,
 +                                       build_int_cst (TREE_TYPE (*vr0min), 1));
            }
          else
            goto give_up;
@@@ -7768,8 -7955,7 +7894,8 @@@ intersect_ranges (enum value_range_typ
          if (mineq)
            {
              if (TREE_CODE (vr1max) == INTEGER_CST)
 -              *vr0min = int_const_binop (PLUS_EXPR, vr1max, integer_one_node);
 +              *vr0min = int_const_binop (PLUS_EXPR, vr1max,
 +                                         build_int_cst (TREE_TYPE (vr1max), 1));
              else
                *vr0min = vr1max;
            }
            {
              if (TREE_CODE (vr1min) == INTEGER_CST)
                *vr0max = int_const_binop (MINUS_EXPR, vr1min,
 -                                         integer_one_node);
 +                                         build_int_cst (TREE_TYPE (vr1min), 1));
              else
                *vr0max = vr1min;
            }
              *vr0type = VR_RANGE;
              if (TREE_CODE (*vr0max) == INTEGER_CST)
                *vr0min = int_const_binop (PLUS_EXPR, *vr0max,
 -                                         integer_one_node);
 +                                         build_int_cst (TREE_TYPE (*vr0max), 1));
              else
                *vr0min = *vr0max;
              *vr0max = vr1max;
              *vr0type = VR_RANGE;
              if (TREE_CODE (*vr0min) == INTEGER_CST)
                *vr0max = int_const_binop (MINUS_EXPR, *vr0min,
 -                                         integer_one_node);
 +                                         build_int_cst (TREE_TYPE (*vr0min), 1));
              else
                *vr0max = *vr0min;
              *vr0min = vr1min;
        {
          if (TREE_CODE (vr1min) == INTEGER_CST)
            *vr0max = int_const_binop (MINUS_EXPR, vr1min,
 -                                     integer_one_node);
 +                                     build_int_cst (TREE_TYPE (vr1min), 1));
          else
            *vr0max = vr1min;
        }
          *vr0type = VR_RANGE;
          if (TREE_CODE (*vr0max) == INTEGER_CST)
            *vr0min = int_const_binop (PLUS_EXPR, *vr0max,
 -                                     integer_one_node);
 +                                     build_int_cst (TREE_TYPE (*vr0max), 1));
          else
            *vr0min = *vr0max;
          *vr0max = vr1max;
        {
          if (TREE_CODE (vr1max) == INTEGER_CST)
            *vr0min = int_const_binop (PLUS_EXPR, vr1max,
 -                                     integer_one_node);
 +                                     build_int_cst (TREE_TYPE (vr1max), 1));
          else
            *vr0min = vr1max;
        }
          *vr0type = VR_RANGE;
          if (TREE_CODE (*vr0min) == INTEGER_CST)
            *vr0max = int_const_binop (MINUS_EXPR, *vr0min,
 -                                     integer_one_node);
 +                                     build_int_cst (TREE_TYPE (*vr0min), 1));
          else
            *vr0max = *vr0min;
          *vr0min = vr1min;
@@@ -8341,8 -8527,7 +8467,8 @@@ simplify_truth_ops_using_ranges (gimple
    if (rhs_code == EQ_EXPR)
      {
        if (TREE_CODE (op1) == INTEGER_CST)
 -      op1 = int_const_binop (BIT_XOR_EXPR, op1, integer_one_node);
 +      op1 = int_const_binop (BIT_XOR_EXPR, op1, 
 +                             build_int_cst (TREE_TYPE (op1), 1));
        else
        return false;
      }
@@@ -8528,9 -8713,9 +8654,9 @@@ simplify_bit_ops_using_ranges (gimple_s
    tree op = NULL_TREE;
    value_range_t vr0 = VR_INITIALIZER;
    value_range_t vr1 = VR_INITIALIZER;
 -  double_int may_be_nonzero0, may_be_nonzero1;
 -  double_int must_be_nonzero0, must_be_nonzero1;
 -  double_int mask;
 +  wide_int may_be_nonzero0, may_be_nonzero1;
 +  wide_int must_be_nonzero0, must_be_nonzero1;
 +  wide_int mask;
  
    if (TREE_CODE (op0) == SSA_NAME)
      vr0 = *(get_value_range (op0));
    else
      return false;
  
 -  if (!zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0, &must_be_nonzero0))
 +  if (!zero_nonzero_bits_from_vr (TREE_TYPE (op0), &vr0, &may_be_nonzero0, &must_be_nonzero0))
      return false;
 -  if (!zero_nonzero_bits_from_vr (&vr1, &may_be_nonzero1, &must_be_nonzero1))
 +  if (!zero_nonzero_bits_from_vr (TREE_TYPE (op1), &vr1, &may_be_nonzero1, &must_be_nonzero1))
      return false;
  
    switch (gimple_assign_rhs_code (stmt))
      {
      case BIT_AND_EXPR:
        mask = may_be_nonzero0.and_not (must_be_nonzero1);
 -      if (mask.is_zero ())
 +      if (mask == 0)
        {
          op = op0;
          break;
        }
        mask = may_be_nonzero1.and_not (must_be_nonzero0);
 -      if (mask.is_zero ())
 +      if (mask == 0)
        {
          op = op1;
          break;
        break;
      case BIT_IOR_EXPR:
        mask = may_be_nonzero0.and_not (must_be_nonzero1);
 -      if (mask.is_zero ())
 +      if (mask == 0)
        {
          op = op1;
          break;
        }
        mask = may_be_nonzero1.and_not (must_be_nonzero0);
 -      if (mask.is_zero ())
 +      if (mask == 0)
        {
          op = op0;
          break;
@@@ -8661,12 -8846,11 +8787,12 @@@ test_for_singularity (enum tree_code co
     by PRECISION and UNSIGNED_P.  */
  
  static bool
 -range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
 +range_fits_type_p (value_range_t *vr, unsigned dest_precision, signop dest_sgn)
  {
    tree src_type;
    unsigned src_precision;
 -  double_int tem;
 +  widest_int tem;
 +  signop src_sgn;
  
    /* We can only handle integral and pointer types.  */
    src_type = TREE_TYPE (vr->min);
        && !POINTER_TYPE_P (src_type))
      return false;
  
 -  /* An extension is fine unless VR is signed and unsigned_p,
 +  /* An extension is fine unless VR is SIGNED and dest_sgn is UNSIGNED,
       and so is an identity transform.  */
    src_precision = TYPE_PRECISION (TREE_TYPE (vr->min));
 -  if ((src_precision < precision
 -       && !(unsigned_p && !TYPE_UNSIGNED (src_type)))
 -      || (src_precision == precision
 -        && TYPE_UNSIGNED (src_type) == unsigned_p))
 +  src_sgn = TYPE_SIGN (src_type);
 +  if ((src_precision < dest_precision
 +       && !(dest_sgn == UNSIGNED && src_sgn == SIGNED))
 +      || (src_precision == dest_precision && src_sgn == dest_sgn))
      return true;
  
    /* Now we can only handle ranges with constant bounds.  */
        || TREE_CODE (vr->max) != INTEGER_CST)
      return false;
  
 -  /* For sign changes, the MSB of the double_int has to be clear.
 +  /* For sign changes, the MSB of the wide_int has to be clear.
       An unsigned value with its MSB set cannot be represented by
 -     a signed double_int, while a negative value cannot be represented
 -     by an unsigned double_int.  */
 -  if (TYPE_UNSIGNED (src_type) != unsigned_p
 -      && (TREE_INT_CST_HIGH (vr->min) | TREE_INT_CST_HIGH (vr->max)) < 0)
 +     a signed wide_int, while a negative value cannot be represented
 +     by an unsigned wide_int.  */
 +  if (src_sgn != dest_sgn
 +      && (wi::lts_p (vr->min, 0) || wi::lts_p (vr->max, 0)))
      return false;
  
    /* Then we can perform the conversion on both ends and compare
       the result for equality.  */
 -  tem = tree_to_double_int (vr->min).ext (precision, unsigned_p);
 -  if (tree_to_double_int (vr->min) != tem)
 +  tem = wi::ext (wi::to_widest (vr->min), dest_precision, dest_sgn);
 +  if (tem != wi::to_widest (vr->min))
      return false;
 -  tem = tree_to_double_int (vr->max).ext (precision, unsigned_p);
 -  if (tree_to_double_int (vr->max) != tem)
 +  tem = wi::ext (wi::to_widest (vr->max), dest_precision, dest_sgn);
 +  if (tem != wi::to_widest (vr->max))
      return false;
  
    return true;
@@@ -8818,7 -9002,7 +8944,7 @@@ simplify_cond_using_ranges (gimple stmt
          if (range_int_cst_p (vr)
              && range_fits_type_p (vr,
                                    TYPE_PRECISION (TREE_TYPE (op0)),
 -                                  TYPE_UNSIGNED (TREE_TYPE (op0)))
 +                                  TYPE_SIGN (TREE_TYPE (op0)))
              && int_fits_type_p (op1, TREE_TYPE (innerop))
              /* The range must not have overflowed, or if it did overflow
                 we must not be wrapping/trapping overflow and optimizing
@@@ -8963,9 -9147,9 +9089,9 @@@ simplify_conversion_using_ranges (gimpl
    tree innerop, middleop, finaltype;
    gimple def_stmt;
    value_range_t *innervr;
 -  bool inner_unsigned_p, middle_unsigned_p, final_unsigned_p;
 +  signop inner_sgn, middle_sgn, final_sgn;
    unsigned inner_prec, middle_prec, final_prec;
 -  double_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
 +  widest_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
  
    finaltype = TREE_TYPE (gimple_assign_lhs (stmt));
    if (!INTEGRAL_TYPE_P (finaltype))
  
    /* Simulate the conversion chain to check if the result is equal if
       the middle conversion is removed.  */
 -  innermin = tree_to_double_int (innervr->min);
 -  innermax = tree_to_double_int (innervr->max);
 +  innermin = wi::to_widest (innervr->min);
 +  innermax = wi::to_widest (innervr->max);
  
    inner_prec = TYPE_PRECISION (TREE_TYPE (innerop));
    middle_prec = TYPE_PRECISION (TREE_TYPE (middleop));
  
    /* If the first conversion is not injective, the second must not
       be widening.  */
 -  if ((innermax - innermin).ugt (double_int::mask (middle_prec))
 +  if (wi::gtu_p (innermax - innermin,
 +               wi::mask <widest_int> (middle_prec, false))
        && middle_prec < final_prec)
      return false;
    /* We also want a medium value so that we can track the effect that
       narrowing conversions with sign change have.  */
 -  inner_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (innerop));
 -  if (inner_unsigned_p)
 -    innermed = double_int::mask (inner_prec).lrshift (1, inner_prec);
 +  inner_sgn = TYPE_SIGN (TREE_TYPE (innerop));
 +  if (inner_sgn == UNSIGNED)
 +    innermed = wi::shifted_mask <widest_int> (1, inner_prec - 1, false);
    else
 -    innermed = double_int_zero;
 -  if (innermin.cmp (innermed, inner_unsigned_p) >= 0
 -      || innermed.cmp (innermax, inner_unsigned_p) >= 0)
 +    innermed = 0;
 +  if (wi::cmp (innermin, innermed, inner_sgn) >= 0
 +      || wi::cmp (innermed, innermax, inner_sgn) >= 0)
      innermed = innermin;
  
 -  middle_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (middleop));
 -  middlemin = innermin.ext (middle_prec, middle_unsigned_p);
 -  middlemed = innermed.ext (middle_prec, middle_unsigned_p);
 -  middlemax = innermax.ext (middle_prec, middle_unsigned_p);
 +  middle_sgn = TYPE_SIGN (TREE_TYPE (middleop));
 +  middlemin = wi::ext (innermin, middle_prec, middle_sgn);
 +  middlemed = wi::ext (innermed, middle_prec, middle_sgn);
 +  middlemax = wi::ext (innermax, middle_prec, middle_sgn);
  
    /* Require that the final conversion applied to both the original
       and the intermediate range produces the same result.  */
 -  final_unsigned_p = TYPE_UNSIGNED (finaltype);
 -  if (middlemin.ext (final_prec, final_unsigned_p)
 -       != innermin.ext (final_prec, final_unsigned_p)
 -      || middlemed.ext (final_prec, final_unsigned_p)
 -       != innermed.ext (final_prec, final_unsigned_p)
 -      || middlemax.ext (final_prec, final_unsigned_p)
 -       != innermax.ext (final_prec, final_unsigned_p))
 +  final_sgn = TYPE_SIGN (finaltype);
 +  if (wi::ext (middlemin, final_prec, final_sgn)
 +       != wi::ext (innermin, final_prec, final_sgn)
 +      || wi::ext (middlemed, final_prec, final_sgn)
 +       != wi::ext (innermed, final_prec, final_sgn)
 +      || wi::ext (middlemax, final_prec, final_sgn)
 +       != wi::ext (innermax, final_prec, final_sgn))
      return false;
  
    gimple_assign_set_rhs1 (stmt, innerop);
@@@ -9056,7 -9239,8 +9182,7 @@@ simplify_float_conversion_using_ranges 
    if (TYPE_UNSIGNED (TREE_TYPE (rhs1))
        && (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)), 0)
          != CODE_FOR_nothing)
 -      && range_fits_type_p (vr, GET_MODE_PRECISION
 -                                (TYPE_MODE (TREE_TYPE (rhs1))), 0))
 +      && range_fits_type_p (vr, TYPE_PRECISION (TREE_TYPE (rhs1)), SIGNED))
      mode = TYPE_MODE (TREE_TYPE (rhs1));
    /* If we can do the conversion in the current input mode do nothing.  */
    else if (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)),
             or if the value-range does not fit in the signed type
             try with a wider mode.  */
          if (can_float_p (fltmode, mode, 0) != CODE_FOR_nothing
 -            && range_fits_type_p (vr, GET_MODE_PRECISION (mode), 0))
 +            && range_fits_type_p (vr, GET_MODE_PRECISION (mode), SIGNED))
            break;
  
          mode = GET_MODE_WIDER_MODE (mode);
@@@ -9105,7 -9289,6 +9231,7 @@@ static boo
  simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
  {
    gimple stmt = gsi_stmt (*gsi);
 +
    if (is_gimple_assign (stmt))
      {
        enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
@@@ -9450,8 -9633,9 +9576,8 @@@ vrp_finalize (void
            && (TREE_CODE (vr_value[i]->max) == INTEGER_CST))
          {
            if (vr_value[i]->type == VR_RANGE)
 -            set_range_info (name,
 -                            tree_to_double_int (vr_value[i]->min),
 -                            tree_to_double_int (vr_value[i]->max));
 +            set_range_info (name, wi::to_widest (vr_value[i]->min),
 +                            wi::to_widest (vr_value[i]->max));
            else if (vr_value[i]->type == VR_ANTI_RANGE)
              {
                /* VR_ANTI_RANGE ~[min, max] is encoded compactly as
                if (TYPE_UNSIGNED (TREE_TYPE (name))
                    && integer_zerop (vr_value[i]->min)
                    && integer_zerop (vr_value[i]->max))
 -                set_range_info (name,
 -                                double_int_one,
 -                                double_int::max_value
 -                                (TYPE_PRECISION (TREE_TYPE (name)), true));
 +                {
 +                  unsigned prec = TYPE_PRECISION (TREE_TYPE (name));
 +                  set_range_info (name, 1,
 +                                  wi::mask <widest_int> (prec, false));
 +                }
                else
                  set_range_info (name,
 -                                tree_to_double_int (vr_value[i]->max)
 -                                + double_int_one,
 -                                tree_to_double_int (vr_value[i]->min)
 -                                - double_int_one);
 +                                wi::to_widest (vr_value[i]->max) + 1,
 +                                wi::to_widest (vr_value[i]->min) - 1);
              }
          }
        }
diff --combined gcc/tree.c
index 9344f7f042931fb237daea179a26cf8d8cdaf60c,332751a3a786cc7167b8272ee879155a23b7444f..133dbb16da9117f15877a7ae9d4f3056ae1225cf
@@@ -47,7 -47,13 +47,13 @@@ along with GCC; see the file COPYING3
  #include "tree-inline.h"
  #include "tree-iterator.h"
  #include "basic-block.h"
- #include "tree-ssa.h"
+ #include "bitmap.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-phinodes.h"
+ #include "tree-ssanames.h"
+ #include "tree-dfa.h"
  #include "params.h"
  #include "pointer-set.h"
  #include "tree-pass.h"
  #include "diagnostic.h"
  #include "tree-diagnostic.h"
  #include "tree-pretty-print.h"
- #include "cgraph.h"
  #include "except.h"
  #include "debug.h"
  #include "intl.h"
 +#include "wide-int.h"
  
  /* Tree code classes.  */
  
@@@ -559,7 -563,7 +564,7 @@@ init_ttree (void
    int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
                                        int_cst_hash_eq, NULL);
  
 -  int_cst_node = make_node (INTEGER_CST);
 +  int_cst_node = make_int_cst (1, 1);
  
    cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
                                          cl_option_hash_eq, NULL);
@@@ -662,7 -666,7 +667,7 @@@ decl_assembler_name_hash (const_tree as
  
  /* Compute the number of bytes occupied by a tree with code CODE.
     This function cannot be used for nodes that have variable sizes,
 -   including TREE_VEC, STRING_CST, and CALL_EXPR.  */
 +   including TREE_VEC, INTEGER_CST, STRING_CST, and CALL_EXPR.  */
  size_t
  tree_code_size (enum tree_code code)
  {
      case tcc_constant:  /* a constant */
        switch (code)
        {
 -      case INTEGER_CST:       return sizeof (struct tree_int_cst);
 +      case INTEGER_CST:       gcc_unreachable ();
        case REAL_CST:          return sizeof (struct tree_real_cst);
        case FIXED_CST:         return sizeof (struct tree_fixed_cst);
        case COMPLEX_CST:       return sizeof (struct tree_complex);
@@@ -757,10 -761,6 +762,10 @@@ tree_size (const_tree node
    const enum tree_code code = TREE_CODE (node);
    switch (code)
      {
 +    case INTEGER_CST:
 +      return (sizeof (struct tree_int_cst)
 +            + (TREE_INT_CST_EXT_NUNITS (node) - 1) * sizeof (HOST_WIDE_INT));
 +
      case TREE_BINFO:
        return (offsetof (struct tree_binfo, base_binfos)
              + vec<tree, va_gc>
@@@ -893,9 -893,8 +898,9 @@@ allocate_decl_uid (void
  
  /* Return a newly allocated node of code CODE.  For decl and type
     nodes, some other fields are initialized.  The rest of the node is
 -   initialized to zero.  This function cannot be used for TREE_VEC or
 -   OMP_CLAUSE nodes, which is enforced by asserts in tree_code_size.
 +   initialized to zero.  This function cannot be used for TREE_VEC,
 +   INTEGER_CST or OMP_CLAUSE nodes, which is enforced by asserts in
 +   tree_code_size.
  
     Achoo!  I got a code in the node.  */
  
@@@ -1083,53 -1082,6 +1088,53 @@@ copy_list (tree list
  }
  
  \f
 +/* Return the value that TREE_INT_CST_EXT_NUNITS should have for an
 +   INTEGER_CST with value CST and type TYPE.   */
 +
 +static unsigned int
 +get_int_cst_ext_nunits (tree type, const wide_int &cst)
 +{
 +  gcc_checking_assert (cst.get_precision () == TYPE_PRECISION (type));
 +  /* We need an extra zero HWI if CST is an unsigned integer with its
 +     upper bit set, and if CST occupies a whole number of HWIs.  */
 +  if (TYPE_UNSIGNED (type)
 +      && wi::neg_p (cst)
 +      && (cst.get_precision () % HOST_BITS_PER_WIDE_INT) == 0)
 +    return cst.get_precision () / HOST_BITS_PER_WIDE_INT + 1;
 +  return cst.get_len ();
 +}
 +
 +/* Return a new INTEGER_CST with value CST and type TYPE.  */
 +
 +static tree
 +build_new_int_cst (tree type, const wide_int &cst)
 +{
 +  unsigned int len = cst.get_len ();
 +  unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
 +  tree nt = make_int_cst (len, ext_len);
 +
 +  if (len < ext_len)
 +    {
 +      --ext_len;
 +      TREE_INT_CST_ELT (nt, ext_len) = 0;
 +      for (unsigned int i = len; i < ext_len; ++i)
 +      TREE_INT_CST_ELT (nt, i) = -1;
 +    }
 +  else if (TYPE_UNSIGNED (type)
 +         && cst.get_precision () < len * HOST_BITS_PER_WIDE_INT)
 +    {
 +      len--;
 +      TREE_INT_CST_ELT (nt, len)
 +      = zext_hwi (cst.elt (len),
 +                  cst.get_precision () % HOST_BITS_PER_WIDE_INT);
 +    }
 +
 +  for (unsigned int i = 0; i < len; i++)
 +    TREE_INT_CST_ELT (nt, i) = cst.elt (i);
 +  TREE_TYPE (nt) = type;
 +  return nt;
 +}
 +
  /* Create an INT_CST node with a LOW value sign extended to TYPE.  */
  
  tree
@@@ -1139,13 -1091,7 +1144,13 @@@ build_int_cst (tree type, HOST_WIDE_IN
    if (!type)
      type = integer_type_node;
  
 -  return double_int_to_tree (type, double_int::from_shwi (low));
 +  return wide_int_to_tree (type, wi::shwi (low, TYPE_PRECISION (type)));
 +}
 +
 +tree
 +build_int_cstu (tree type, unsigned HOST_WIDE_INT cst)
 +{
 +  return wide_int_to_tree (type, wi::uhwi (cst, TYPE_PRECISION (type)));
  }
  
  /* Create an INT_CST node with a LOW value sign extended to TYPE.  */
@@@ -1154,7 -1100,8 +1159,7 @@@ tre
  build_int_cst_type (tree type, HOST_WIDE_INT low)
  {
    gcc_assert (type);
 -
 -  return double_int_to_tree (type, double_int::from_shwi (low));
 +  return wide_int_to_tree (type, wi::shwi (low, TYPE_PRECISION (type)));
  }
  
  /* Constructs tree in type TYPE from with value given by CST.  Signedness
  tree
  double_int_to_tree (tree type, double_int cst)
  {
 -  bool sign_extended_type = !TYPE_UNSIGNED (type);
 -
 -  cst = cst.ext (TYPE_PRECISION (type), !sign_extended_type);
 -
 -  return build_int_cst_wide (type, cst.low, cst.high);
 -}
 -
 -/* Returns true if CST fits into range of TYPE.  Signedness of CST is assumed
 -   to be the same as the signedness of TYPE.  */
 -
 -bool
 -double_int_fits_to_tree_p (const_tree type, double_int cst)
 -{
 -  bool sign_extended_type = !TYPE_UNSIGNED (type);
 -
 -  double_int ext
 -    = cst.ext (TYPE_PRECISION (type), !sign_extended_type);
 -
 -  return cst == ext;
 +  return wide_int_to_tree (type, widest_int::from (cst, TYPE_SIGN (type)));
  }
  
 -/* We force the double_int CST to the range of the type TYPE by sign or
 +/* We force the wide_int CST to the range of the type TYPE by sign or
     zero extending it.  OVERFLOWABLE indicates if we are interested in
     overflow of the value, when >0 we are only interested in signed
     overflow, for <0 we are interested in any overflow.  OVERFLOWED
          OVERFLOWED is nonzero,
          or OVERFLOWABLE is >0 and signed overflow occurs
          or OVERFLOWABLE is <0 and any overflow occurs
 -   We return a new tree node for the extended double_int.  The node
 +   We return a new tree node for the extended wide_int.  The node
     is shared if no overflow flags are set.  */
  
  
  tree
 -force_fit_type_double (tree type, double_int cst, int overflowable,
 -                     bool overflowed)
 +force_fit_type (tree type, const wide_int_ref &cst,
 +              int overflowable, bool overflowed)
  {
 -  bool sign_extended_type = !TYPE_UNSIGNED (type);
 +  signop sign = TYPE_SIGN (type);
  
    /* If we need to set overflow flags, return a new unshared node.  */
 -  if (overflowed || !double_int_fits_to_tree_p (type, cst))
 +  if (overflowed || !wi::fits_to_tree_p (cst, type))
      {
        if (overflowed
          || overflowable < 0
 -        || (overflowable > 0 && sign_extended_type))
 +        || (overflowable > 0 && sign == SIGNED))
        {
 -        tree t = make_node (INTEGER_CST);
 -        TREE_INT_CST (t)
 -          = cst.ext (TYPE_PRECISION (type), !sign_extended_type);
 -        TREE_TYPE (t) = type;
 +        wide_int tmp = wide_int::from (cst, TYPE_PRECISION (type), sign);
 +        tree t = build_new_int_cst (type, tmp);
          TREE_OVERFLOW (t) = 1;
          return t;
        }
      }
  
    /* Else build a shared node.  */
 -  return double_int_to_tree (type, cst);
 +  return wide_int_to_tree (type, cst);
  }
  
  /* These are the hash table functions for the hash table of INTEGER_CST
@@@ -1214,13 -1181,9 +1219,13 @@@ static hashval_
  int_cst_hash_hash (const void *x)
  {
    const_tree const t = (const_tree) x;
 +  hashval_t code = htab_hash_pointer (TREE_TYPE (t));
 +  int i;
 +
 +  for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
 +    code ^= TREE_INT_CST_ELT (t, i);
  
 -  return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
 -        ^ htab_hash_pointer (TREE_TYPE (t)));
 +  return code;
  }
  
  /* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
@@@ -1232,60 -1195,35 +1237,61 @@@ int_cst_hash_eq (const void *x, const v
    const_tree const xt = (const_tree) x;
    const_tree const yt = (const_tree) y;
  
 -  return (TREE_TYPE (xt) == TREE_TYPE (yt)
 -        && TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
 -        && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt));
 +  if (TREE_TYPE (xt) != TREE_TYPE (yt)
 +      || TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt)
 +      || TREE_INT_CST_EXT_NUNITS (xt) != TREE_INT_CST_EXT_NUNITS (yt))
 +    return false;
 +
 +  for (int i = 0; i < TREE_INT_CST_NUNITS (xt); i++)
 +    if (TREE_INT_CST_ELT (xt, i) != TREE_INT_CST_ELT (yt, i))
 +      return false;
 +
 +  return true;
  }
  
 -/* Create an INT_CST node of TYPE and value HI:LOW.
 +/* Create an INT_CST node of TYPE and value CST.
     The returned node is always shared.  For small integers we use a
 -   per-type vector cache, for larger ones we use a single hash table.  */
 +   per-type vector cache, for larger ones we use a single hash table.
 +   The value is extended from it's precision according to the sign of
 +   the type to be a multiple of HOST_BITS_PER_WIDE_INT.  This defines
 +   the upper bits and ensures that hashing and value equality based
 +   upon the underlying HOST_WIDE_INTs works without masking.  */
  
  tree
 -build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
 +wide_int_to_tree (tree type, const wide_int_ref &pcst)
  {
    tree t;
    int ix = -1;
    int limit = 0;
  
    gcc_assert (type);
 +  unsigned int prec = TYPE_PRECISION (type);
 +  signop sgn = TYPE_SIGN (type);
 +
 +  /* Verify that everything is canonical.  */
 +  int l = pcst.get_len ();
 +  if (l > 1)
 +    {
 +      if (pcst.elt (l - 1) == 0)
 +      gcc_assert (pcst.elt (l - 2) < 0);
 +      if (pcst.elt (l - 1) == (HOST_WIDE_INT) -1)
 +      gcc_assert (pcst.elt (l - 2) >= 0);
 +    }
 +
 +  wide_int cst = wide_int::from (pcst, prec, sgn);
 +  unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
  
    switch (TREE_CODE (type))
      {
      case NULLPTR_TYPE:
 -      gcc_assert (hi == 0 && low == 0);
 +      gcc_assert (cst == 0);
        /* Fallthru.  */
  
      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;
      case BOOLEAN_TYPE:
        /* Cache false or true.  */
        limit = 2;
 -      if (!hi && low < 2)
 -      ix = low;
 +      if (wi::leu_p (cst, 1))
 +      ix = cst.to_uhwi ();
        break;
  
      case INTEGER_TYPE:
      case OFFSET_TYPE:
 -      if (TYPE_UNSIGNED (type))
 +      if (TYPE_SIGN (type) == UNSIGNED)
        {
          /* Cache 0..N */
          limit = INTEGER_SHARE_LIMIT;
 -        if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
 -          ix = low;
 +
 +        /* This is a little hokie, but if the prec is smaller than
 +           what is necessary to hold INTEGER_SHARE_LIMIT, then the
 +           obvious test will not get the correct answer.  */
 +        if (prec < HOST_BITS_PER_WIDE_INT)
 +          {
 +            if (cst.to_uhwi () < (unsigned HOST_WIDE_INT) INTEGER_SHARE_LIMIT)
 +              ix = cst.to_uhwi ();
 +          }
 +        else if (wi::ltu_p (cst, INTEGER_SHARE_LIMIT))
 +          ix = cst.to_uhwi ();
        }
        else
        {
          /* Cache -1..N */
          limit = INTEGER_SHARE_LIMIT + 1;
 -        if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
 -          ix = low + 1;
 -        else if (hi == -1 && low == -(unsigned HOST_WIDE_INT)1)
 +
 +        if (cst == -1)
            ix = 0;
 +        else if (!wi::neg_p (cst))
 +          {
 +            if (prec < HOST_BITS_PER_WIDE_INT)
 +              {
 +                if (cst.to_shwi () < INTEGER_SHARE_LIMIT)
 +                  ix = cst.to_shwi () + 1;
 +              }
 +            else if (wi::lts_p (cst, INTEGER_SHARE_LIMIT))
 +              ix = cst.to_shwi () + 1;
 +          }
        }
        break;
  
        gcc_unreachable ();
      }
  
 -  if (ix >= 0)
 +  if (ext_len == 1)
      {
 -      /* Look for it in the type's vector of small shared ints.  */
 -      if (!TYPE_CACHED_VALUES_P (type))
 +      /* We just need to store a single HOST_WIDE_INT.  */
 +      HOST_WIDE_INT hwi;
 +      if (TYPE_UNSIGNED (type))
 +      hwi = cst.to_uhwi ();
 +      else
 +      hwi = cst.to_shwi ();
 +      if (ix >= 0)
        {
 -        TYPE_CACHED_VALUES_P (type) = 1;
 -        TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
 -      }
 +        /* Look for it in the type's vector of small shared ints.  */
 +        if (!TYPE_CACHED_VALUES_P (type))
 +          {
 +            TYPE_CACHED_VALUES_P (type) = 1;
 +            TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
 +          }
  
 -      t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
 -      if (t)
 -      {
 -        /* Make sure no one is clobbering the shared constant.  */
 -        gcc_assert (TREE_TYPE (t) == type);
 -        gcc_assert (TREE_INT_CST_LOW (t) == low);
 -        gcc_assert (TREE_INT_CST_HIGH (t) == hi);
 +        t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
 +        if (t)
 +          /* Make sure no one is clobbering the shared constant.  */
 +          gcc_assert (TREE_TYPE (t) == type
 +                      && TREE_INT_CST_NUNITS (t) == 1
 +                      && TREE_INT_CST_EXT_NUNITS (t) == 1
 +                      && TREE_INT_CST_ELT (t, 0) == hwi);
 +        else
 +          {
 +            /* Create a new shared int.  */
 +            t = build_new_int_cst (type, cst);
 +            TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
 +          }
        }
        else
        {
 -        /* Create a new shared int.  */
 -        t = make_node (INTEGER_CST);
 +        /* Use the cache of larger shared ints, using int_cst_node as
 +           a temporary.  */
 +        void **slot;
  
 -        TREE_INT_CST_LOW (t) = low;
 -        TREE_INT_CST_HIGH (t) = hi;
 -        TREE_TYPE (t) = type;
 +        TREE_INT_CST_ELT (int_cst_node, 0) = hwi;
 +        TREE_TYPE (int_cst_node) = type;
  
 -        TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
 +        slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
 +        t = (tree) *slot;
 +        if (!t)
 +          {
 +            /* Insert this one into the hash table.  */
 +            t = int_cst_node;
 +            *slot = t;
 +            /* Make a new node for next time round.  */
 +            int_cst_node = make_int_cst (1, 1);
 +          }
        }
      }
    else
      {
 -      /* Use the cache of larger shared ints.  */
 +      /* The value either hashes properly or we drop it on the floor
 +       for the gc to take care of.  There will not be enough of them
 +       to worry about.  */
        void **slot;
  
 -      TREE_INT_CST_LOW (int_cst_node) = low;
 -      TREE_INT_CST_HIGH (int_cst_node) = hi;
 -      TREE_TYPE (int_cst_node) = type;
 -
 -      slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
 +      tree nt = build_new_int_cst (type, cst);
 +      slot = htab_find_slot (int_cst_hash_table, nt, INSERT);
        t = (tree) *slot;
        if (!t)
        {
          /* Insert this one into the hash table.  */
 -        t = int_cst_node;
 +        t = nt;
          *slot = t;
 -        /* Make a new node for next time round.  */
 -        int_cst_node = make_node (INTEGER_CST);
        }
      }
  
  cache_integer_cst (tree t)
  {
    tree type = TREE_TYPE (t);
 -  HOST_WIDE_INT hi = TREE_INT_CST_HIGH (t);
 -  unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (t);
    int ix = -1;
    int limit = 0;
 +  int prec = TYPE_PRECISION (type);
  
    gcc_assert (!TREE_OVERFLOW (t));
  
    switch (TREE_CODE (type))
      {
      case NULLPTR_TYPE:
 -      gcc_assert (hi == 0 && low == 0);
 +      gcc_assert (integer_zerop (t));
        /* Fallthru.  */
  
      case POINTER_TYPE:
      case REFERENCE_TYPE:
        /* Cache NULL pointer.  */
 -      if (!hi && !low)
 +      if (integer_zerop (t))
        {
          limit = 1;
          ix = 0;
      case BOOLEAN_TYPE:
        /* Cache false or true.  */
        limit = 2;
 -      if (!hi && low < 2)
 -      ix = low;
 +      if (wi::ltu_p (t, 2))
 +      ix = TREE_INT_CST_ELT (t, 0);
        break;
  
      case INTEGER_TYPE:
        {
          /* Cache 0..N */
          limit = INTEGER_SHARE_LIMIT;
 -        if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
 -          ix = low;
 +
 +        /* This is a little hokie, but if the prec is smaller than
 +           what is necessary to hold INTEGER_SHARE_LIMIT, then the
 +           obvious test will not get the correct answer.  */
 +        if (prec < HOST_BITS_PER_WIDE_INT)
 +          {
 +            if (tree_to_uhwi (t) < (unsigned HOST_WIDE_INT) INTEGER_SHARE_LIMIT)
 +              ix = tree_to_uhwi (t);
 +          }
 +        else if (wi::ltu_p (t, INTEGER_SHARE_LIMIT))
 +          ix = tree_to_uhwi (t);
        }
        else
        {
          /* Cache -1..N */
          limit = INTEGER_SHARE_LIMIT + 1;
 -        if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
 -          ix = low + 1;
 -        else if (hi == -1 && low == -(unsigned HOST_WIDE_INT)1)
 +
 +        if (integer_minus_onep (t))
            ix = 0;
 +        else if (!wi::neg_p (t))
 +          {
 +            if (prec < HOST_BITS_PER_WIDE_INT)
 +              {
 +                if (tree_to_shwi (t) < INTEGER_SHARE_LIMIT)
 +                  ix = tree_to_shwi (t) + 1;
 +              }
 +            else if (wi::ltu_p (t, INTEGER_SHARE_LIMIT))
 +              ix = tree_to_shwi (t) + 1;
 +          }
        }
        break;
  
        /* If there is already an entry for the number verify it's the
           same.  */
        if (*slot)
 -      {
 -        gcc_assert (TREE_INT_CST_LOW ((tree)*slot) == low
 -                    && TREE_INT_CST_HIGH ((tree)*slot) == hi);
 -        return;
 -      }
 -      /* Otherwise insert this one into the hash table.  */
 -      *slot = t;
 +      gcc_assert (wi::eq_p (tree (*slot), t));
 +      else
 +      /* Otherwise insert this one into the hash table.  */
 +      *slot = t;
      }
  }
  
  tree
  build_low_bits_mask (tree type, unsigned bits)
  {
 -  double_int mask;
 -
    gcc_assert (bits <= TYPE_PRECISION (type));
  
 -  if (bits == TYPE_PRECISION (type)
 -      && !TYPE_UNSIGNED (type))
 -    /* Sign extended all-ones mask.  */
 -    mask = double_int_minus_one;
 -  else
 -    mask = double_int::mask (bits);
 -
 -  return build_int_cst_wide (type, mask.low, mask.high);
 -}
 -
 -/* Checks that X is integer constant that can be expressed in (unsigned)
 -   HOST_WIDE_INT without loss of precision.  */
 -
 -bool
 -cst_and_fits_in_hwi (const_tree x)
 -{
 -  if (TREE_CODE (x) != INTEGER_CST)
 -    return false;
 -
 -  if (TYPE_PRECISION (TREE_TYPE (x)) > HOST_BITS_PER_WIDE_INT)
 -    return false;
 -
 -  return (TREE_INT_CST_HIGH (x) == 0
 -        || TREE_INT_CST_HIGH (x) == -1);
 +  return wide_int_to_tree (type, wi::mask (bits, false,
 +                                         TYPE_PRECISION (type)));
  }
  
  /* Build a newly constructed TREE_VEC node of length LEN.  */
@@@ -1774,8 -1684,8 +1780,8 @@@ real_value_from_int_cst (const_tree typ
    memset (&d, 0, sizeof d);
  
    real_from_integer (&d, type ? TYPE_MODE (type) : VOIDmode,
 -                   TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i),
 -                   TYPE_UNSIGNED (TREE_TYPE (i)));
 +                   wide_int (i),
 +                   TYPE_SIGN (TREE_TYPE (i)));
    return d;
  }
  
@@@ -2013,28 -1923,6 +2019,28 @@@ build_case_label (tree low_value, tree 
    return t;
  }
  
 +/* Build a newly constructed INETEGER_CST node of length LEN.  */
 +
 +tree
 +make_int_cst_stat (int len, int ext_len MEM_STAT_DECL)
 +{
 +  tree t;
 +  int length = (ext_len - 1) * sizeof (tree) + sizeof (struct tree_int_cst);
 +
 +  gcc_assert (len);
 +  record_node_allocation_statistics (INTEGER_CST, length);
 +
 +  t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT);
 +
 +  TREE_SET_CODE (t, INTEGER_CST);
 +  TREE_INT_CST_NUNITS (t) = len;
 +  TREE_INT_CST_EXT_NUNITS (t) = ext_len;
 +
 +  TREE_CONSTANT (t) = 1;
 +
 +  return t;
 +}
 +
  /* Build a newly constructed TREE_VEC node of length LEN.  */
  
  tree
@@@ -2064,7 -1952,8 +2070,7 @@@ integer_zerop (const_tree expr
    switch (TREE_CODE (expr))
      {
      case INTEGER_CST:
 -      return (TREE_INT_CST_LOW (expr) == 0
 -            && TREE_INT_CST_HIGH (expr) == 0);
 +      return wi::eq_p (expr, 0);
      case COMPLEX_CST:
        return (integer_zerop (TREE_REALPART (expr))
              && integer_zerop (TREE_IMAGPART (expr)));
@@@ -2092,7 -1981,8 +2098,7 @@@ integer_onep (const_tree expr
    switch (TREE_CODE (expr))
      {
      case INTEGER_CST:
 -      return (TREE_INT_CST_LOW (expr) == 1
 -            && TREE_INT_CST_HIGH (expr) == 0);
 +      return wi::eq_p (expr, 1);
      case COMPLEX_CST:
        return (integer_onep (TREE_REALPART (expr))
              && integer_zerop (TREE_IMAGPART (expr)));
  int
  integer_all_onesp (const_tree expr)
  {
 -  int prec;
 -  int uns;
 -
    STRIP_NOPS (expr);
  
    if (TREE_CODE (expr) == COMPLEX_CST
    else if (TREE_CODE (expr) != INTEGER_CST)
      return 0;
  
 -  uns = TYPE_UNSIGNED (TREE_TYPE (expr));
 -  if (TREE_INT_CST_LOW (expr) == ~(unsigned HOST_WIDE_INT) 0
 -      && TREE_INT_CST_HIGH (expr) == -1)
 -    return 1;
 -  if (!uns)
 -    return 0;
 -
 -  prec = TYPE_PRECISION (TREE_TYPE (expr));
 -  if (prec >= HOST_BITS_PER_WIDE_INT)
 -    {
 -      HOST_WIDE_INT high_value;
 -      int shift_amount;
 -
 -      shift_amount = prec - HOST_BITS_PER_WIDE_INT;
 -
 -      /* Can not handle precisions greater than twice the host int size.  */
 -      gcc_assert (shift_amount <= HOST_BITS_PER_WIDE_INT);
 -      if (shift_amount == HOST_BITS_PER_WIDE_INT)
 -      /* Shifting by the host word size is undefined according to the ANSI
 -         standard, so we must handle this as a special case.  */
 -      high_value = -1;
 -      else
 -      high_value = ((HOST_WIDE_INT) 1 << shift_amount) - 1;
 -
 -      return (TREE_INT_CST_LOW (expr) == ~(unsigned HOST_WIDE_INT) 0
 -            && TREE_INT_CST_HIGH (expr) == high_value);
 -    }
 -  else
 -    return TREE_INT_CST_LOW (expr) == ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
 +  return wi::max_value (TYPE_PRECISION (TREE_TYPE (expr)), UNSIGNED) == expr;
  }
  
  /* Return 1 if EXPR is the integer constant minus one.  */
@@@ -2157,6 -2078,9 +2163,6 @@@ integer_minus_onep (const_tree expr
  int
  integer_pow2p (const_tree expr)
  {
 -  int prec;
 -  unsigned HOST_WIDE_INT high, low;
 -
    STRIP_NOPS (expr);
  
    if (TREE_CODE (expr) == COMPLEX_CST
    if (TREE_CODE (expr) != INTEGER_CST)
      return 0;
  
 -  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.  */
 -
 -  if (prec == HOST_BITS_PER_DOUBLE_INT)
 -    ;
 -  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);
 -    }
 -
 -  if (high == 0 && low == 0)
 -    return 0;
 -
 -  return ((high == 0 && (low & (low - 1)) == 0)
 -        || (low == 0 && (high & (high - 1)) == 0));
 +  return wi::popcount (expr) == 1;
  }
  
  /* Return 1 if EXPR is an integer constant other than zero or a
@@@ -2179,7 -2125,8 +2185,7 @@@ integer_nonzerop (const_tree expr
    STRIP_NOPS (expr);
  
    return ((TREE_CODE (expr) == INTEGER_CST
 -         && (TREE_INT_CST_LOW (expr) != 0
 -             || TREE_INT_CST_HIGH (expr) != 0))
 +         && !wi::eq_p (expr, 0))
          || (TREE_CODE (expr) == COMPLEX_CST
              && (integer_nonzerop (TREE_REALPART (expr))
                  || integer_nonzerop (TREE_IMAGPART (expr)))));
@@@ -2200,12 -2147,34 +2206,12 @@@ fixed_zerop (const_tree expr
  int
  tree_log2 (const_tree expr)
  {
 -  int prec;
 -  HOST_WIDE_INT high, low;
 -
    STRIP_NOPS (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.  */
 -
 -  if (prec == HOST_BITS_PER_DOUBLE_INT)
 -    ;
 -  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 + exact_log2 (high)
 -        : exact_log2 (low));
 +  return wi::exact_log2 (expr);
  }
  
  /* Similar, but return the largest integer Y such that 2 ** Y is less
  int
  tree_floor_log2 (const_tree expr)
  {
 -  int prec;
 -  HOST_WIDE_INT high, low;
 -
    STRIP_NOPS (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.  */
  
@@@ -2640,11 -2745,14 +2759,11 @@@ int_size_in_bytes (const_tree type
  
    type = TYPE_MAIN_VARIANT (type);
    t = TYPE_SIZE_UNIT (type);
 -  if (t == 0
 -      || TREE_CODE (t) != INTEGER_CST
 -      || TREE_INT_CST_HIGH (t) != 0
 -      /* If the result would appear negative, it's too big to represent.  */
 -      || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
 -    return -1;
  
 -  return TREE_INT_CST_LOW (t);
 +  if (t && cst_fits_uhwi_p (t))
 +    return tree_to_hwi (t);
 +  else
 +    return -1;
  }
  
  /* Return the maximum size of TYPE (in bytes) as a wide integer
@@@ -2662,8 -2770,8 +2781,8 @@@ max_int_size_in_bytes (const_tree type
      {
        size_tree = TYPE_ARRAY_MAX_SIZE (type);
  
 -      if (size_tree && host_integerp (size_tree, 1))
 -      size = tree_low_cst (size_tree, 1);
 +      if (size_tree && tree_fits_uhwi_p (size_tree))
 +      size = tree_to_uhwi (size_tree);
      }
  
    /* If we still haven't been able to get a size, see if the language
      {
        size_tree = lang_hooks.types.max_size (type);
  
 -      if (size_tree && host_integerp (size_tree, 1))
 -      size = tree_low_cst (size_tree, 1);
 +      if (size_tree && tree_fits_uhwi_p (size_tree))
 +      size = tree_to_uhwi (size_tree);
      }
  
    return size;
@@@ -2709,7 -2817,7 +2828,7 @@@ bit_position (const_tree field
  HOST_WIDE_INT
  int_bit_position (const_tree field)
  {
 -  return tree_low_cst (bit_position (field), 0);
 +  return tree_to_shwi (bit_position (field));
  }
  \f
  /* Return the byte position of FIELD, in bytes from the start of the record.
@@@ -2729,7 -2837,7 +2848,7 @@@ byte_position (const_tree field
  HOST_WIDE_INT
  int_byte_position (const_tree field)
  {
 -  return tree_low_cst (byte_position (field), 0);
 +  return tree_to_shwi (byte_position (field));
  }
  \f
  /* Return the strictest alignment, in bits, that T is known to have.  */
@@@ -3279,6 -3387,7 +3398,7 @@@ type_contains_placeholder_1 (const_tre
    switch (TREE_CODE (type))
      {
      case VOID_TYPE:
+     case POINTER_BOUNDS_TYPE:
      case COMPLEX_TYPE:
      case ENUMERAL_TYPE:
      case BOOLEAN_TYPE:
@@@ -4303,10 -4412,11 +4423,10 @@@ build_simple_mem_ref_loc (location_t lo
  
  /* Return the constant offset of a MEM_REF or TARGET_MEM_REF tree T.  */
  
 -double_int
 +offset_int
  mem_ref_offset (const_tree t)
  {
 -  tree toff = TREE_OPERAND (t, 1);
 -  return tree_to_double_int (toff).sext (TYPE_PRECISION (TREE_TYPE (toff)));
 +  return offset_int::from (TREE_OPERAND (t, 1), SIGNED);
  }
  
  /* Return an invariant ADDR_EXPR of type TYPE taking the address of BASE
@@@ -4530,8 -4640,6 +4650,8 @@@ build_type_attribute_qual_variant (tre
      {
        hashval_t hashcode = 0;
        tree ntype;
 +      int i;
 +      tree t;
        enum tree_code code = TREE_CODE (ttype);
  
        /* Building a distinct copy of a tagged type is inappropriate; it
                                              hashcode);
          break;
        case INTEGER_TYPE:
 -        hashcode = iterative_hash_object
 -          (TREE_INT_CST_LOW (TYPE_MAX_VALUE (ntype)), hashcode);
 -        hashcode = iterative_hash_object
 -          (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode);
 +        t = TYPE_MAX_VALUE (ntype);
 +        for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
 +          hashcode = iterative_hash_object (TREE_INT_CST_ELT (t, i), hashcode);
          break;
        case REAL_TYPE:
        case FIXED_POINT_TYPE:
@@@ -5013,7 -5122,7 +5133,7 @@@ free_lang_data_in_decl (tree decl
      {
        struct cgraph_node *node;
        if (!(node = cgraph_get_node (decl))
-         || (!node->symbol.definition && !node->clones))
+         || (!node->definition && !node->clones))
        {
          if (node)
            cgraph_release_function_body (node);
           DECL_VINDEX referring to itself into a vtable slot number as it
         should.  Happens with functions that are copied and then forgotten
         about.  Just clear it, it won't matter anymore.  */
 -      if (DECL_VINDEX (decl) && !host_integerp (DECL_VINDEX (decl), 0))
 +      if (DECL_VINDEX (decl) && !tree_fits_shwi_p (DECL_VINDEX (decl)))
        DECL_VINDEX (decl) = NULL_TREE;
      }
    else if (TREE_CODE (decl) == VAR_DECL)
@@@ -5427,14 -5536,14 +5547,14 @@@ find_decls_types_in_node (struct cgraph
    unsigned ix;
    tree t;
  
-   find_decls_types (n->symbol.decl, fld);
+   find_decls_types (n->decl, fld);
  
-   if (!gimple_has_body_p (n->symbol.decl))
+   if (!gimple_has_body_p (n->decl))
      return;
  
    gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
  
-   fn = DECL_STRUCT_FUNCTION (n->symbol.decl);
+   fn = DECL_STRUCT_FUNCTION (n->decl);
  
    /* Traverse locals. */
    FOR_EACH_LOCAL_DECL (fn, ix, t)
  static void
  find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld)
  {
-   find_decls_types (v->symbol.decl, fld);
+   find_decls_types (v->decl, fld);
  }
  
  /* If T needs an assembler name, have one created for it.  */
@@@ -6587,8 -6696,6 +6707,8 @@@ type_hash_eq (const void *va, const voi
      case INTEGER_TYPE:
      case REAL_TYPE:
      case BOOLEAN_TYPE:
 +      if (TYPE_PRECISION (a->type) != TYPE_PRECISION (b->type))
 +        return false;
        return ((TYPE_MAX_VALUE (a->type) == TYPE_MAX_VALUE (b->type)
               || tree_int_cst_equal (TYPE_MAX_VALUE (a->type),
                                      TYPE_MAX_VALUE (b->type)))
@@@ -6887,7 -6994,8 +7007,7 @@@ tree_int_cst_equal (const_tree t1, cons
  
    if (TREE_CODE (t1) == INTEGER_CST
        && TREE_CODE (t2) == INTEGER_CST
 -      && TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
 -      && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2))
 +      && wi::to_widest (t1) == wi::to_widest (t2))
      return 1;
  
    return 0;
  int
  tree_int_cst_lt (const_tree t1, const_tree t2)
  {
 -  if (t1 == t2)
 -    return 0;
 -
 -  if (TYPE_UNSIGNED (TREE_TYPE (t1)) != TYPE_UNSIGNED (TREE_TYPE (t2)))
 -    {
 -      int t1_sgn = tree_int_cst_sgn (t1);
 -      int t2_sgn = tree_int_cst_sgn (t2);
 -
 -      if (t1_sgn < t2_sgn)
 -      return 1;
 -      else if (t1_sgn > t2_sgn)
 -      return 0;
 -      /* Otherwise, both are non-negative, so we compare them as
 -       unsigned just in case one of them would overflow a signed
 -       type.  */
 -    }
 -  else if (!TYPE_UNSIGNED (TREE_TYPE (t1)))
 -    return INT_CST_LT (t1, t2);
 -
 -  return INT_CST_LT_UNSIGNED (t1, t2);
 +  return INT_CST_LT (t1, t2);
  }
  
  /* Returns -1 if T1 < T2, 0 if T1 == T2, and 1 if T1 > T2.  */
  int
  tree_int_cst_compare (const_tree t1, const_tree t2)
  {
 -  if (tree_int_cst_lt (t1, t2))
 -    return -1;
 -  else if (tree_int_cst_lt (t2, t1))
 -    return 1;
 -  else
 -    return 0;
 -}
 -
 -/* Return 1 if T is an INTEGER_CST that can be manipulated efficiently on
 -   the host.  If POS is zero, the value can be represented in a single
 -   HOST_WIDE_INT.  If POS is nonzero, the value must be non-negative and can
 -   be represented in a single unsigned HOST_WIDE_INT.  */
 -
 -int
 -host_integerp (const_tree t, int pos)
 -{
 -  if (t == NULL_TREE)
 -    return 0;
 -
 -  return (TREE_CODE (t) == INTEGER_CST
 -        && ((TREE_INT_CST_HIGH (t) == 0
 -             && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
 -            || (! pos && TREE_INT_CST_HIGH (t) == -1
 -                && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
 -                && !TYPE_UNSIGNED (TREE_TYPE (t)))
 -            || (pos && TREE_INT_CST_HIGH (t) == 0)));
 -}
 -
 -/* Return the HOST_WIDE_INT least significant bits of T if it is an
 -   INTEGER_CST and there is no overflow.  POS is nonzero if the result must
 -   be non-negative.  We must be able to satisfy the above conditions.  */
 -
 -HOST_WIDE_INT
 -tree_low_cst (const_tree t, int pos)
 -{
 -  gcc_assert (host_integerp (t, pos));
 -  return TREE_INT_CST_LOW (t);
 +  return wi::cmps (wi::to_widest (t1), wi::to_widest (t2));
  }
  
  /* Return the HOST_WIDE_INT least significant bits of T, a sizetype
  HOST_WIDE_INT
  size_low_cst (const_tree t)
  {
 -  double_int d = tree_to_double_int (t);
 -  return d.sext (TYPE_PRECISION (TREE_TYPE (t))).low;
 +  HOST_WIDE_INT w = TREE_INT_CST_ELT (t, 0);
 +  int prec = TYPE_PRECISION (TREE_TYPE (t));
 +  if (prec < HOST_BITS_PER_WIDE_INT)
 +    return sext_hwi (w, prec);
 +  return w;
  }
  
  /* Return the most significant (sign) bit of T.  */
  tree_int_cst_sign_bit (const_tree t)
  {
    unsigned bitno = TYPE_PRECISION (TREE_TYPE (t)) - 1;
 -  unsigned HOST_WIDE_INT w;
 -
 -  if (bitno < HOST_BITS_PER_WIDE_INT)
 -    w = TREE_INT_CST_LOW (t);
 -  else
 -    {
 -      w = TREE_INT_CST_HIGH (t);
 -      bitno -= HOST_BITS_PER_WIDE_INT;
 -    }
  
 -  return (w >> bitno) & 1;
 +  return wi::extract_uhwi (t, bitno, 1);
  }
  
  /* Return an indication of the sign of the integer constant T.
  int
  tree_int_cst_sgn (const_tree t)
  {
 -  if (TREE_INT_CST_LOW (t) == 0 && TREE_INT_CST_HIGH (t) == 0)
 +  if (wi::eq_p (t, 0))
      return 0;
    else if (TYPE_UNSIGNED (TREE_TYPE (t)))
      return 1;
 -  else if (TREE_INT_CST_HIGH (t) < 0)
 +  else if (wi::neg_p (t))
      return -1;
    else
      return 1;
     signed or unsigned type, UNSIGNEDP says which.  */
  
  unsigned int
 -tree_int_cst_min_precision (tree value, bool unsignedp)
 +tree_int_cst_min_precision (tree value, signop sgn)
  {
    /* If the value is negative, compute its negative minus 1.  The latter
       adjustment is because the absolute value of the largest negative value
    if (integer_zerop (value))
      return 1;
    else
 -    return tree_floor_log2 (value) + 1 + !unsignedp;
 +    return tree_floor_log2 (value) + 1 + (sgn == SIGNED ? 1 : 0) ;
  }
  
  /* Compare two constructor-element-type constants.  Return 1 if the lists
@@@ -7034,7 -7203,8 +7154,7 @@@ simple_cst_equal (const_tree t1, const_
    switch (code1)
      {
      case INTEGER_CST:
 -      return (TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
 -            && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2));
 +      return wi::to_widest (t1) == wi::to_widest (t2);
  
      case REAL_CST:
        return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
@@@ -7170,11 -7340,11 +7290,11 @@@ compare_tree_int (const_tree t, unsigne
  {
    if (tree_int_cst_sgn (t) < 0)
      return -1;
 -  else if (TREE_INT_CST_HIGH (t) != 0)
 +  else if (!cst_fits_uhwi_p (t))
      return 1;
 -  else if (TREE_INT_CST_LOW (t) == u)
 +  else if ((unsigned HOST_WIDE_INT) tree_to_hwi (t) == u)
      return 0;
 -  else if (TREE_INT_CST_LOW (t) < u)
 +  else if ((unsigned HOST_WIDE_INT) tree_to_hwi (t) < u)
      return -1;
    else
      return 1;
  bool
  valid_constant_size_p (const_tree size)
  {
 -  if (! host_integerp (size, 1)
 +  if (! tree_fits_uhwi_p (size)
        || TREE_OVERFLOW (size)
        || tree_int_cst_sign_bit (size) != 0)
      return false;
@@@ -7306,9 -7476,8 +7426,9 @@@ iterative_hash_expr (const_tree t, hash
      /* Alas, constants aren't shared, so we can't rely on pointer
         identity.  */
      case INTEGER_CST:
 -      val = iterative_hash_host_wide_int (TREE_INT_CST_LOW (t), val);
 -      return iterative_hash_host_wide_int (TREE_INT_CST_HIGH (t), val);
 +      for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
 +      val = iterative_hash_host_wide_int (TREE_INT_CST_ELT (t, i), val);
 +      return val;
      case REAL_CST:
        {
        unsigned int val2 = real_hash (TREE_REAL_CST_PTR (t));
@@@ -7639,8 -7808,8 +7759,8 @@@ build_nonstandard_integer_type (unsigne
      fixup_signed_type (itype);
  
    ret = itype;
 -  if (host_integerp (TYPE_MAX_VALUE (itype), 1))
 -    ret = type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype);
 +  if (tree_fits_uhwi_p (TYPE_MAX_VALUE (itype)))
 +    ret = type_hash_canon (tree_to_uhwi (TYPE_MAX_VALUE (itype)), itype);
    if (precision <= MAX_INT_CACHED_PREC)
      nonstandard_integer_type_cache[precision + unsignedp] = ret;
  
@@@ -8581,10 -8750,10 +8701,10 @@@ get_narrower (tree op, int *unsignedp_p
        && TREE_CODE (TREE_TYPE (op)) != FIXED_POINT_TYPE
        /* Ensure field is laid out already.  */
        && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
 -      && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
 +      && tree_fits_uhwi_p (DECL_SIZE (TREE_OPERAND (op, 1))))
      {
        unsigned HOST_WIDE_INT innerprec
 -      = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
 +      = tree_to_uhwi (DECL_SIZE (TREE_OPERAND (op, 1)));
        int unsignedp = (DECL_UNSIGNED (TREE_OPERAND (op, 1))
                       || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
        tree type = lang_hooks.types.type_for_size (innerprec, unsignedp);
@@@ -8619,8 -8788,11 +8739,8 @@@ boo
  int_fits_type_p (const_tree c, const_tree type)
  {
    tree type_low_bound, type_high_bound;
 -  bool ok_for_low_bound, ok_for_high_bound, unsc;
 -  double_int dc, dd;
 -
 -  dc = tree_to_double_int (c);
 -  unsc = TYPE_UNSIGNED (TREE_TYPE (c));
 +  bool ok_for_low_bound, ok_for_high_bound;
 +  signop sgn_c = TYPE_SIGN (TREE_TYPE (c));
  
  retry:
    type_low_bound = TYPE_MIN_VALUE (type);
    /* If at least one bound of the type is a constant integer, we can check
       ourselves and maybe make a decision. If no such decision is possible, but
       this type is a subtype, try checking against that.  Otherwise, use
 -     double_int_fits_to_tree_p, which checks against the precision.
 +     fits_to_tree_p, which checks against the precision.
  
       Compute the status for each possibly constant bound, and return if we see
       one does not match. Use ok_for_xxx_bound for this purpose, assigning -1
    /* Check if c >= type_low_bound.  */
    if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
      {
 -      dd = tree_to_double_int (type_low_bound);
 -      if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_low_bound)))
 -      {
 -        int c_neg = (!unsc && dc.is_negative ());
 -        int t_neg = (unsc && dd.is_negative ());
 -
 -        if (c_neg && !t_neg)
 -          return false;
 -        if ((c_neg || !t_neg) && dc.ult (dd))
 -          return false;
 -      }
 -      else if (dc.cmp (dd, unsc) < 0)
 +      if (INT_CST_LT (c, type_low_bound))
        return false;
        ok_for_low_bound = true;
      }
    /* Check if c <= type_high_bound.  */
    if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
      {
 -      dd = tree_to_double_int (type_high_bound);
 -      if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_high_bound)))
 -      {
 -        int c_neg = (!unsc && dc.is_negative ());
 -        int t_neg = (unsc && dd.is_negative ());
 -
 -        if (t_neg && !c_neg)
 -          return false;
 -        if ((t_neg || !c_neg) && dc.ugt (dd))
 -          return false;
 -      }
 -      else if (dc.cmp (dd, unsc) > 0)
 +      if (INT_CST_LT (type_high_bound, c))
        return false;
        ok_for_high_bound = true;
      }
    /* Perform some generic filtering which may allow making a decision
       even if the bounds are not constant.  First, negative integers
       never fit in unsigned types, */
 -  if (TYPE_UNSIGNED (type) && !unsc && dc.is_negative ())
 +  if (TYPE_UNSIGNED (type) && sgn_c == SIGNED && wi::neg_p (c))
      return false;
  
    /* Second, narrower types always fit in wider ones.  */
      return true;
  
    /* Third, unsigned integers with top bit set never fit signed types.  */
 -  if (! TYPE_UNSIGNED (type) && unsc)
 -    {
 -      int prec = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (c))) - 1;
 -      if (prec < HOST_BITS_PER_WIDE_INT)
 -      {
 -        if (((((unsigned HOST_WIDE_INT) 1) << prec) & dc.low) != 0)
 -          return false;
 -        }
 -      else if (((((unsigned HOST_WIDE_INT) 1)
 -               << (prec - HOST_BITS_PER_WIDE_INT)) & dc.high) != 0)
 -      return false;
 -    }
 +  if (!TYPE_UNSIGNED (type) && sgn_c == UNSIGNED && wi::neg_p (c))
 +    return false;
  
    /* If we haven't been able to decide at this point, there nothing more we
       can check ourselves here.  Look at the base type if we have one and it
        goto retry;
      }
  
 -  /* Or to double_int_fits_to_tree_p, if nothing else.  */
 -  return double_int_fits_to_tree_p (type, dc);
 +  /* Or to fits_to_tree_p, if nothing else.  */
 +  return wi::fits_to_tree_p (c, type);
  }
  
  /* Stores bounds of an integer TYPE in MIN and MAX.  If TYPE has non-constant
@@@ -8699,25 -8903,33 +8819,25 @@@ get_type_static_bounds (const_tree type
  {
    if (!POINTER_TYPE_P (type) && TYPE_MIN_VALUE (type)
        && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
 -    mpz_set_double_int (min, tree_to_double_int (TYPE_MIN_VALUE (type)),
 -                      TYPE_UNSIGNED (type));
 +    wi::to_mpz (TYPE_MIN_VALUE (type), min, TYPE_SIGN (type));
    else
      {
        if (TYPE_UNSIGNED (type))
        mpz_set_ui (min, 0);
        else
        {
 -        double_int mn;
 -        mn = double_int::mask (TYPE_PRECISION (type) - 1);
 -        mn = (mn + double_int_one).sext (TYPE_PRECISION (type));
 -        mpz_set_double_int (min, mn, false);
 +        wide_int mn = wi::min_value (TYPE_PRECISION (type), SIGNED);
 +        wi::to_mpz (mn, min, SIGNED);
        }
      }
  
    if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type)
        && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST)
 -    mpz_set_double_int (max, tree_to_double_int (TYPE_MAX_VALUE (type)),
 -                      TYPE_UNSIGNED (type));
 +    wi::to_mpz (TYPE_MAX_VALUE (type), max, TYPE_SIGN (type));
    else
      {
 -      if (TYPE_UNSIGNED (type))
 -      mpz_set_double_int (max, double_int::mask (TYPE_PRECISION (type)),
 -                          true);
 -      else
 -      mpz_set_double_int (max, double_int::mask (TYPE_PRECISION (type) - 1),
 -                          true);
 +      wide_int mn = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
 +      wi::to_mpz (mn, max, TYPE_SIGN (type));
      }
  }
  
@@@ -9382,18 -9594,6 +9502,18 @@@ tree_contains_struct_check_failed (cons
  }
  
  
 +/* Similar to above, except that the check is for the bounds of a TREE_VEC's
 +   (dynamically sized) vector.  */
 +
 +void
 +tree_int_cst_elt_check_failed (int idx, int len, const char *file, int line,
 +                             const char *function)
 +{
 +  internal_error
 +    ("tree check: accessed elt %d of tree_int_cst with %d elts in %s, at %s:%d",
 +     idx + 1, len, function, trim_filename (file), line);
 +}
 +
  /* Similar to above, except that the check is for the bounds of a TREE_VEC's
     (dynamically sized) vector.  */
  
@@@ -9622,11 -9822,13 +9742,11 @@@ build_common_tree_nodes (bool signed_ch
  #endif
  
    /* Define a boolean type.  This type only represents boolean values but
 -     may be larger than char depending on the value of BOOL_TYPE_SIZE.
 -     Front ends which want to override this size (i.e. Java) can redefine
 -     boolean_type_node before calling build_common_tree_nodes_2.  */
 +     may be larger than char depending on the value of BOOL_TYPE_SIZE.  */
    boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
    TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
 -  TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1);
    TYPE_PRECISION (boolean_type_node) = 1;
 +  TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1);
  
    /* Define what type to use for size_t.  */
    if (strcmp (SIZE_TYPE, "unsigned int") == 0)
    void_type_node = make_node (VOID_TYPE);
    layout_type (void_type_node);
  
+   pointer_bounds_type_node = targetm.chkp_bound_type ();
    /* We are not going to have real types in C with less than byte alignment,
       so we might as well not have any types that claim to have it.  */
    TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
@@@ -10182,10 -10386,10 +10304,10 @@@ build_vector_type_for_mode (tree innert
      case MODE_INT:
        /* Check that there are no leftover bits.  */
        gcc_assert (GET_MODE_BITSIZE (mode)
 -                % TREE_INT_CST_LOW (TYPE_SIZE (innertype)) == 0);
 +                % tree_to_hwi (TYPE_SIZE (innertype)) == 0);
  
        nunits = GET_MODE_BITSIZE (mode)
 -             / TREE_INT_CST_LOW (TYPE_SIZE (innertype));
 +             / tree_to_hwi (TYPE_SIZE (innertype));
        break;
  
      default:
@@@ -10570,10 -10774,11 +10692,10 @@@ HOST_WIDE_IN
  int_cst_value (const_tree x)
  {
    unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
 -  unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x);
 +  unsigned HOST_WIDE_INT val = tree_to_hwi (x);
  
    /* Make sure the sign-extended value will fit in a HOST_WIDE_INT.  */
 -  gcc_assert (TREE_INT_CST_HIGH (x) == 0
 -            || TREE_INT_CST_HIGH (x) == -1);
 +  gcc_assert (cst_fits_shwi_p (x));
  
    if (bits < HOST_BITS_PER_WIDE_INT)
      {
@@@ -10593,20 -10798,16 +10715,20 @@@ HOST_WIDEST_IN
  widest_int_cst_value (const_tree x)
  {
    unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
 -  unsigned HOST_WIDEST_INT val = TREE_INT_CST_LOW (x);
 +  unsigned HOST_WIDEST_INT val = tree_to_hwi (x);
  
  #if HOST_BITS_PER_WIDEST_INT > HOST_BITS_PER_WIDE_INT
    gcc_assert (HOST_BITS_PER_WIDEST_INT >= HOST_BITS_PER_DOUBLE_INT);
 -  val |= (((unsigned HOST_WIDEST_INT) TREE_INT_CST_HIGH (x))
 -        << HOST_BITS_PER_WIDE_INT);
 +  gcc_assert (TREE_INT_CST_NUNITS (x) == 2);
 +  
 +  if (TREE_INT_CST_NUNITS (x) == 1)
 +    val = HOST_WIDE_INT (val);
 +  else
 +    val |= (((unsigned HOST_WIDEST_INT) TREE_INT_CST_ELT (x, 1))
 +          << HOST_BITS_PER_WIDE_INT);
  #else
    /* Make sure the sign-extended value will fit in a HOST_WIDE_INT.  */
 -  gcc_assert (TREE_INT_CST_HIGH (x) == 0
 -            || TREE_INT_CST_HIGH (x) == -1);
 +  gcc_assert (TREE_INT_CST_NUNITS (x) == 1);
  #endif
  
    if (bits < HOST_BITS_PER_WIDEST_INT)
@@@ -10691,6 -10892,7 +10813,6 @@@ truth_type_for (tree type
  tree
  upper_bound_in_type (tree outer, tree inner)
  {
 -  double_int high;
    unsigned int det = 0;
    unsigned oprec = TYPE_PRECISION (outer);
    unsigned iprec = TYPE_PRECISION (inner);
        gcc_unreachable ();
      }
  
 -  /* Compute 2^^prec - 1.  */
 -  if (prec <= HOST_BITS_PER_WIDE_INT)
 -    {
 -      high.high = 0;
 -      high.low = ((~(unsigned HOST_WIDE_INT) 0)
 -          >> (HOST_BITS_PER_WIDE_INT - prec));
 -    }
 -  else
 -    {
 -      high.high = ((~(unsigned HOST_WIDE_INT) 0)
 -          >> (HOST_BITS_PER_DOUBLE_INT - prec));
 -      high.low = ~(unsigned HOST_WIDE_INT) 0;
 -    }
 -
 -  return double_int_to_tree (outer, high);
 +  return wide_int_to_tree (outer, 
 +                         wi::mask (prec, false, TYPE_PRECISION (outer)));
  }
  
  /* Returns the smallest value obtainable by casting something in INNER type to
  tree
  lower_bound_in_type (tree outer, tree inner)
  {
 -  double_int low;
    unsigned oprec = TYPE_PRECISION (outer);
    unsigned iprec = TYPE_PRECISION (inner);
  
         contains all values of INNER type.  In particular, both INNER
         and OUTER types have zero in common.  */
        || (oprec > iprec && TYPE_UNSIGNED (inner)))
 -    low.low = low.high = 0;
 +    return build_int_cst (outer, 0);
    else
      {
        /* If we are widening a signed type to another signed type, we
         precision or narrowing to a signed type, we want to obtain
         -2^(oprec-1).  */
        unsigned prec = oprec > iprec ? iprec : oprec;
 -
 -      if (prec <= HOST_BITS_PER_WIDE_INT)
 -      {
 -        low.high = ~(unsigned HOST_WIDE_INT) 0;
 -        low.low = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
 -      }
 -      else
 -      {
 -        low.high = ((~(unsigned HOST_WIDE_INT) 0)
 -              << (prec - HOST_BITS_PER_WIDE_INT - 1));
 -        low.low = 0;
 -      }
 +      return wide_int_to_tree (outer, 
 +                             wi::mask (prec - 1, true,
 +                                       TYPE_PRECISION (outer)));
      }
 -
 -  return double_int_to_tree (outer, low);
  }
  
  /* Return nonzero if two operands that are suitable for PHI nodes are
@@@ -10784,12 -11011,42 +10906,12 @@@ operand_equal_for_phi_arg_p (const_tre
    return operand_equal_p (arg0, arg1, 0);
  }
  
 -/* Returns number of zeros at the end of binary representation of X.
 -
 -   ??? Use ffs if available?  */
 +/* Returns number of zeros at the end of binary representation of X.  */
  
  tree
  num_ending_zeros (const_tree x)
  {
 -  unsigned HOST_WIDE_INT fr, nfr;
 -  unsigned num, abits;
 -  tree type = TREE_TYPE (x);
 -
 -  if (TREE_INT_CST_LOW (x) == 0)
 -    {
 -      num = HOST_BITS_PER_WIDE_INT;
 -      fr = TREE_INT_CST_HIGH (x);
 -    }
 -  else
 -    {
 -      num = 0;
 -      fr = TREE_INT_CST_LOW (x);
 -    }
 -
 -  for (abits = HOST_BITS_PER_WIDE_INT / 2; abits; abits /= 2)
 -    {
 -      nfr = fr >> abits;
 -      if (nfr << abits == fr)
 -      {
 -        num += abits;
 -        fr = nfr;
 -      }
 -    }
 -
 -  if (num > TYPE_PRECISION (type))
 -    num = TYPE_PRECISION (type);
 -
 -  return build_int_cst_type (type, num);
 +  return build_int_cst (TREE_TYPE (x), wi::ctz (x));
  }
  
  
@@@ -11960,7 -12217,7 +12082,7 @@@ get_binfo_at_offset (tree binfo, HOST_W
            continue;
  
          pos = int_bit_position (fld);
 -        size = tree_low_cst (DECL_SIZE (fld), 1);
 +        size = tree_to_uhwi (DECL_SIZE (fld));
          if (pos <= offset && (pos + size) > offset)
            break;
        }
diff --combined gcc/tree.def
index 0f9646af0710cfbcc95c5fa358846b2741d95877,399b5af6cbeecbf5719415f4642976890189651b..47acd7b941dc8c05495f9694a4e800662e5e4a90
@@@ -232,6 -232,11 +232,11 @@@ DEFTREECODE (QUAL_UNION_TYPE, "qual_uni
  /* The void type in C */
  DEFTREECODE (VOID_TYPE, "void_type", tcc_type, 0)
  
+ /* Type to hold bounds for a pointer.
+    Has TYPE_PRECISION component to specify number of bits used
+    by this type.  */
+ DEFTREECODE (POINTER_BOUNDS_TYPE, "pointer_bounds_type", tcc_type, 0)
  /* Type of functions.  Special fields:
     TREE_TYPE              type of value returned.
     TYPE_ARG_TYPES      list of types of arguments expected.
@@@ -257,24 -262,13 +262,24 @@@ DEFTREECODE (LANG_TYPE, "lang_type", tc
  
  /* First, the constants.  */
  
 -/* Contents are in TREE_INT_CST_LOW and TREE_INT_CST_HIGH fields,
 -   32 bits each, giving us a 64 bit constant capability.  INTEGER_CST
 -   nodes can be shared, and therefore should be considered read only.
 -   They should be copied, before setting a flag such as TREE_OVERFLOW.
 -   If an INTEGER_CST has TREE_OVERFLOW already set, it is known to be unique.
 -   INTEGER_CST nodes are created for the integral types, for pointer
 -   types and for vector and float types in some circumstances.  */
 +/* Contents are in an array of HOST_WIDE_INTs.
 +
 +   We often access these constants both in their native precision and
 +   in wider precisions (with the constant being implicitly extended
 +   according to TYPE_SIGN).  In each case, the useful part of the array
 +   may be as wide as the precision requires but may be shorter when all
 +   of the upper bits are sign bits.  The length of the array when accessed
 +   in the constant's native precision is given by TREE_INT_CST_NUNITS.
 +   The length of the array when accessed in wider precisions is given
 +   by TREE_INT_CST_EXT_NUNITS.  Each element can be obtained using
 +   TREE_INT_CST_ELT.
 +
 +   INTEGER_CST nodes can be shared, and therefore should be considered
 +   read only.  They should be copied before setting a flag such as
 +   TREE_OVERFLOW.  If an INTEGER_CST has TREE_OVERFLOW already set,
 +   it is known to be unique.  INTEGER_CST nodes are created for the
 +   integral types, for pointer types and for vector and float types in
 +   some circumstances.  */
  DEFTREECODE (INTEGER_CST, "integer_cst", tcc_constant, 0)
  
  /* Contents are in TREE_REAL_CST field.  */
@@@ -1272,6 -1266,18 +1277,18 @@@ DEFTREECODE (OPTIMIZATION_NODE, "optimi
  /* TARGET_OPTION_NODE.  Node to store the target specific options.  */
  DEFTREECODE (TARGET_OPTION_NODE, "target_option_node", tcc_exceptional, 0)
  
+ /* ANNOTATE_EXPR.
+    Operand 0 is the expression to be annotated.
+    Operand 1 is the annotation id. */
+ DEFTREECODE (ANNOTATE_EXPR, "annotate_expr", tcc_expression, 2)
+ /* Cilk spawn statement
+    Operand 0 is the CALL_EXPR.  */
+ DEFTREECODE (CILK_SPAWN_STMT, "cilk_spawn_stmt", tcc_statement, 1)
+ /* Cilk Sync statement: Does not have any operands.  */
+ DEFTREECODE (CILK_SYNC_STMT, "cilk_sync_stmt", tcc_statement, 0)
  /*
  Local variables:
  mode:c
diff --combined gcc/tree.h
index 43f383fff808c7548a2e165de1a78ca26595379e,920ad07aadde4345b1ec88bcc4ac6b1795239a2d..ec92f843a41f629fba672ab564bb74e0a78f22ea
@@@ -21,7 -21,6 +21,7 @@@ along with GCC; see the file COPYING3
  #define GCC_TREE_H
  
  #include "tree-core.h"
 +#include "wide-int.h"
  
  /* Macros for initializing `tree_contains_struct'.  */
  #define MARK_TS_BASE(C)                                       \
  
  #define TREE_CODE_CLASS(CODE) tree_code_type[(int) (CODE)]
  
- /* Nonzero if CODE represents an exceptional code.  */
+ /* Nonzero if NODE represents an exceptional code.  */
  
- #define EXCEPTIONAL_CLASS_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_exceptional)
+ #define EXCEPTIONAL_CLASS_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_exceptional)
  
- /* Nonzero if CODE represents a constant.  */
+ /* Nonzero if NODE represents a constant.  */
  
- #define CONSTANT_CLASS_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_constant)
+ #define CONSTANT_CLASS_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_constant)
  
- /* Nonzero if CODE represents a type.  */
+ /* Nonzero if NODE represents a type.  */
  
- #define TYPE_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_type)
+ #define TYPE_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_type)
  
- /* Nonzero if CODE represents a declaration.  */
+ /* Nonzero if NODE represents a declaration.  */
  
- #define DECL_P(CODE)\
-         (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_declaration)
+ #define DECL_P(NODE)\
+         (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_declaration)
  
  /* True if NODE designates a variable declaration.  */
  #define VAR_P(NODE) \
  #define VAR_OR_FUNCTION_DECL_P(DECL)\
    (TREE_CODE (DECL) == VAR_DECL || TREE_CODE (DECL) == FUNCTION_DECL)
  
- /* Nonzero if CODE represents a INDIRECT_REF.  Keep these checks in
+ /* Nonzero if NODE represents a INDIRECT_REF.  Keep these checks in
     ascending code order.  */
  
- #define INDIRECT_REF_P(CODE)\
-   (TREE_CODE (CODE) == INDIRECT_REF)
+ #define INDIRECT_REF_P(NODE)\
+   (TREE_CODE (NODE) == INDIRECT_REF)
  
- /* Nonzero if CODE represents a reference.  */
+ /* Nonzero if NODE represents a reference.  */
  
- #define REFERENCE_CLASS_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_reference)
+ #define REFERENCE_CLASS_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_reference)
  
- /* Nonzero if CODE represents a comparison.  */
+ /* Nonzero if NODE represents a comparison.  */
  
- #define COMPARISON_CLASS_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_comparison)
+ #define COMPARISON_CLASS_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_comparison)
  
- /* Nonzero if CODE represents a unary arithmetic expression.  */
+ /* Nonzero if NODE represents a unary arithmetic expression.  */
  
- #define UNARY_CLASS_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_unary)
+ #define UNARY_CLASS_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_unary)
  
- /* Nonzero if CODE represents a binary arithmetic expression.  */
+ /* Nonzero if NODE represents a binary arithmetic expression.  */
  
- #define BINARY_CLASS_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_binary)
+ #define BINARY_CLASS_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_binary)
  
- /* Nonzero if CODE represents a statement expression.  */
+ /* Nonzero if NODE represents a statement expression.  */
  
- #define STATEMENT_CLASS_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_statement)
+ #define STATEMENT_CLASS_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_statement)
  
- /* Nonzero if CODE represents a function call-like expression with a
+ /* Nonzero if NODE represents a function call-like expression with a
     variable-length operand vector.  */
  
- #define VL_EXP_CLASS_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_vl_exp)
+ #define VL_EXP_CLASS_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_vl_exp)
  
- /* Nonzero if CODE represents any other expression.  */
+ /* Nonzero if NODE represents any other expression.  */
  
- #define EXPRESSION_CLASS_P(CODE)\
-       (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_expression)
+ #define EXPRESSION_CLASS_P(NODE)\
+       (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_expression)
  
- /* Returns nonzero iff CODE represents a type or declaration.  */
+ /* Returns nonzero iff NODE represents a type or declaration.  */
  
- #define IS_TYPE_OR_DECL_P(CODE)\
-       (TYPE_P (CODE) || DECL_P (CODE))
+ #define IS_TYPE_OR_DECL_P(NODE)\
+       (TYPE_P (NODE) || DECL_P (NODE))
  
  /* Returns nonzero iff CLASS is the tree-code class of an
     expression.  */
  #define CASE_FLT_FN_REENT(FN) case FN##_R: case FN##F_R: case FN##L_R
  #define CASE_INT_FN(FN) case FN: case FN##L: case FN##LL: case FN##IMAX
  
 +#define NULL_TREE (tree) NULL
 +
  /* Define accessors for the fields that all tree nodes have
     (though some fields are not used for all kinds of nodes).  */
  
  #define NON_TYPE_CHECK(T) \
  (non_type_check ((T), __FILE__, __LINE__, __FUNCTION__))
  
 +#define TREE_INT_CST_ELT_CHECK(T, I) \
 +(*tree_int_cst_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__))
 +
  #define TREE_VEC_ELT_CHECK(T, I) \
  (*(CONST_CAST2 (tree *, typeof (T)*, \
       tree_vec_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__))))
@@@ -333,9 -327,6 +333,9 @@@ extern void tree_not_class_check_faile
                                         const enum tree_code_class,
                                         const char *, int, const char *)
      ATTRIBUTE_NORETURN;
 +extern void tree_int_cst_elt_check_failed (int, int, const char *,
 +                                         int, const char *)
 +    ATTRIBUTE_NORETURN;
  extern void tree_vec_elt_check_failed (int, int, const char *,
                                       int, const char *)
      ATTRIBUTE_NORETURN;
@@@ -373,7 -364,6 +373,7 @@@ extern void omp_clause_range_check_fail
  #define TREE_RANGE_CHECK(T, CODE1, CODE2)     (T)
  #define EXPR_CHECK(T)                         (T)
  #define NON_TYPE_CHECK(T)                     (T)
 +#define TREE_INT_CST_ELT_CHECK(T, I)          ((T)->int_cst.val[I])
  #define TREE_VEC_ELT_CHECK(T, I)              ((T)->vec.a[I])
  #define TREE_OPERAND_CHECK(T, I)              ((T)->exp.operands[I])
  #define TREE_OPERAND_CHECK_CODE(T, CODE, I)   ((T)->exp.operands[I])
  /* Nonzero if this type is a complete type.  */
  #define COMPLETE_TYPE_P(NODE) (TYPE_SIZE (NODE) != NULL_TREE)
  
+ /* Nonzero if this type is a pointer bounds type.  */
+ #define POINTER_BOUNDS_TYPE_P(NODE) \
+   (TREE_CODE (NODE) == POINTER_BOUNDS_TYPE)
+ /* Nonzero if this node has a pointer bounds type.  */
+ #define POINTER_BOUNDS_P(NODE) \
+   (POINTER_BOUNDS_TYPE_P (TREE_TYPE (NODE)))
+ /* Nonzero if this type supposes bounds existence.  */
+ #define BOUNDED_TYPE_P(type) (POINTER_TYPE_P (type))
+ /* Nonzero for objects with bounded type.  */
+ #define BOUNDED_P(node) \
+   BOUNDED_TYPE_P (TREE_TYPE (node))
  /* Nonzero if this type is the (possibly qualified) void type.  */
  #define VOID_TYPE_P(NODE) (TREE_CODE (NODE) == VOID_TYPE)
  
  #define SET_PREDICT_EXPR_OUTCOME(NODE, OUTCOME) \
    (PREDICT_EXPR_CHECK (NODE)->base.addressable_flag = (int) OUTCOME)
  #define PREDICT_EXPR_PREDICTOR(NODE) \
 -  ((enum br_predictor)tree_low_cst (TREE_OPERAND (PREDICT_EXPR_CHECK (NODE), 0), 0))
 +  ((enum br_predictor)tree_to_shwi (TREE_OPERAND (PREDICT_EXPR_CHECK (NODE), 0)))
  
  /* In a VAR_DECL, nonzero means allocate static storage.
     In a FUNCTION_DECL, nonzero if function has been defined.
  /* In integral and pointer types, means an unsigned type.  */
  #define TYPE_UNSIGNED(NODE) (TYPE_CHECK (NODE)->base.u.bits.unsigned_flag)
  
 +/* Same as TYPE_UNSIGNED but converted to SIGNOP.  */
 +#define TYPE_SIGN(NODE) ((signop)TYPE_UNSIGNED(NODE))
 +
  /* True if overflow wraps around for the given integral type.  That
     is, TYPE_MAX + 1 == TYPE_MIN.  */
  #define TYPE_OVERFLOW_WRAPS(TYPE) \
  #define CALL_EXPR_RETURN_SLOT_OPT(NODE) \
    (CALL_EXPR_CHECK (NODE)->base.private_flag)
  
+ /* Cilk keywords accessors.  */
+ #define CILK_SPAWN_FN(NODE) TREE_OPERAND (CILK_SPAWN_STMT_CHECK (NODE), 0)
  /* In a RESULT_DECL, PARM_DECL and VAR_DECL, means that it is
     passed by invisible reference (and the TREE_TYPE is a pointer to the true
     type).  */
  \f
  /* Define additional fields and accessors for nodes representing constants.  */
  
 -/* In an INTEGER_CST node.  These two together make a 2-word integer.
 -   If the data type is signed, the value is sign-extended to 2 words
 -   even though not all of them may really be in use.
 -   In an unsigned constant shorter than 2 words, the extra bits are 0.  */
 -#define TREE_INT_CST(NODE) (INTEGER_CST_CHECK (NODE)->int_cst.int_cst)
 -#define TREE_INT_CST_LOW(NODE) (TREE_INT_CST (NODE).low)
 -#define TREE_INT_CST_HIGH(NODE) (TREE_INT_CST (NODE).high)
 -
 -#define INT_CST_LT(A, B)                              \
 -  (TREE_INT_CST_HIGH (A) < TREE_INT_CST_HIGH (B)      \
 -   || (TREE_INT_CST_HIGH (A) == TREE_INT_CST_HIGH (B) \
 -       && TREE_INT_CST_LOW (A) < TREE_INT_CST_LOW (B)))
 -
 -#define INT_CST_LT_UNSIGNED(A, B)                             \
 -  (((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (A)            \
 -    < (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (B))         \
 -   || (((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (A)                \
 -      == (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (B))      \
 -       && TREE_INT_CST_LOW (A) < TREE_INT_CST_LOW (B)))
 +#define TREE_INT_CST_NUNITS(NODE) \
 +  (INTEGER_CST_CHECK (NODE)->base.u.int_length.unextended)
 +#define TREE_INT_CST_EXT_NUNITS(NODE) \
 +  (INTEGER_CST_CHECK (NODE)->base.u.int_length.extended)
 +#define TREE_INT_CST_ELT(NODE, I) TREE_INT_CST_ELT_CHECK (NODE, I)
 +
 +#define INT_CST_LT(A, B) (wi::lts_p (wi::to_widest (A), wi::to_widest (B)))
 +#define INT_CST_LE(A, B) (wi::les_p (wi::to_widest (A), wi::to_widest (B)))
  
  #define TREE_REAL_CST_PTR(NODE) (REAL_CST_CHECK (NODE)->real_cst.real_cst_ptr)
  #define TREE_REAL_CST(NODE) (*TREE_REAL_CST_PTR (NODE))
     Note that we have to bypass the use of TREE_OPERAND to access
     that field to avoid infinite recursion in expanding the macros.  */
  #define VL_EXP_OPERAND_LENGTH(NODE) \
 -  ((int)TREE_INT_CST_LOW (VL_EXP_CHECK (NODE)->exp.operands[0]))
 +  ((int)tree_to_hwi (VL_EXP_CHECK (NODE)->exp.operands[0]))
  
  /* Nonzero if is_gimple_debug() may possibly hold.  */
  #define MAY_HAVE_DEBUG_STMTS    (flag_var_tracking_assignments)
@@@ -1102,7 -1118,7 +1120,7 @@@ extern void protected_set_expr_locatio
  #define CHREC_VAR(NODE)           TREE_OPERAND (POLYNOMIAL_CHREC_CHECK (NODE), 0)
  #define CHREC_LEFT(NODE)          TREE_OPERAND (POLYNOMIAL_CHREC_CHECK (NODE), 1)
  #define CHREC_RIGHT(NODE)         TREE_OPERAND (POLYNOMIAL_CHREC_CHECK (NODE), 2)
 -#define CHREC_VARIABLE(NODE)      TREE_INT_CST_LOW (CHREC_VAR (NODE))
 +#define CHREC_VARIABLE(NODE)      tree_to_hwi (CHREC_VAR (NODE))
  
  /* LABEL_EXPR accessor. This gives access to the label associated with
     the given label expression.  */
@@@ -2856,30 -2872,6 +2874,30 @@@ non_type_check (tree __t, const char *_
    return __t;
  }
  
 +inline const HOST_WIDE_INT *
 +tree_int_cst_elt_check (const_tree __t, int __i,
 +                      const char *__f, int __l, const char *__g)
 +{
 +  if (TREE_CODE (__t) != INTEGER_CST)
 +    tree_check_failed (__t, __f, __l, __g, INTEGER_CST, 0);
 +  if (__i < 0 || __i >= __t->base.u.int_length.extended)
 +    tree_int_cst_elt_check_failed (__i, __t->base.u.int_length.extended,
 +                                 __f, __l, __g);
 +  return &CONST_CAST_TREE (__t)->int_cst.val[__i];
 +}
 +
 +inline HOST_WIDE_INT *
 +tree_int_cst_elt_check (tree __t, int __i,
 +                      const char *__f, int __l, const char *__g)
 +{
 +  if (TREE_CODE (__t) != INTEGER_CST)
 +    tree_check_failed (__t, __f, __l, __g, INTEGER_CST, 0);
 +  if (__i < 0 || __i >= __t->base.u.int_length.extended)
 +    tree_int_cst_elt_check_failed (__i, __t->base.u.int_length.extended,
 +                                 __f, __l, __g);
 +  return &CONST_CAST_TREE (__t)->int_cst.val[__i];
 +}
 +
  inline tree *
  tree_vec_elt_check (tree __t, int __i,
                      const char *__f, int __l, const char *__g)
@@@ -3111,174 -3103,6 +3129,174 @@@ omp_clause_elt_check (const_tree __t, i
  
  #endif
  
 +/* Checks that X is integer constant that can be expressed in signed
 +   HOST_WIDE_INT without loss of precision.  This function differs
 +   from the tree_fits_* versions in that the signedness of the
 +   type of X is not considered.  */
 +
 +static inline bool
 +cst_fits_shwi_p (const_tree x)
 +{
 +  if (TREE_CODE (x) != INTEGER_CST)
 +    return false;
 +
 +  return TREE_INT_CST_NUNITS (x) == 1;
 +}
 +
 +/* Checks that X is integer constant that can be expressed in signed
 +   HOST_WIDE_INT without loss of precision.  This function differs
 +   from the tree_fits_* versions in that the signedness of the
 +   type of X is not considered.  */
 +
 +static inline bool
 +cst_fits_uhwi_p (const_tree x)
 +{
 +  if (TREE_CODE (x) != INTEGER_CST)
 +    return false;
 +
 +  return TREE_INT_CST_NUNITS (x) == 1 && TREE_INT_CST_ELT (x, 0) >= 0;
 +}
 +
 +/* Return true if T is an INTEGER_CST whose value must be non-negative
 +   and can be represented in a single unsigned HOST_WIDE_INT.  This
 +   function differs from the cst_fits versions in that the signedness
 +   of the type of cst is considered.  */
 +
 +static inline bool
 +tree_fits_uhwi_p (const_tree cst)
 +{
 +  tree type;
 +  if (cst == NULL_TREE)
 +    return false;
 +
 +  type = TREE_TYPE (cst);
 +
 +  if (TREE_CODE (cst) != INTEGER_CST)
 +    return false;
 +
 +  if (TREE_INT_CST_NUNITS (cst) == 1)
 +    {
 +      if ((TYPE_SIGN (type) == UNSIGNED)
 +        && (TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT))
 +      return true;
 +
 +      /* For numbers of unsigned type that are longer than a HWI, if
 +       the top bit of the bottom word is set, and there is not
 +       another element, then this is too large to fit in a single
 +       hwi.  For signed numbers, negative values are not allowed. */
 +      if (TREE_INT_CST_ELT (cst, 0) >= 0)
 +      return true;
 +    }
 +  else if (TREE_INT_CST_NUNITS (cst) == 2)
 +    {
 +      if (TREE_INT_CST_ELT (cst, 1) == 0)
 +      return true;
 +    }
 +  return false;
 +}
 +
 +/* Return true if CST is an INTEGER_CST whose value can be represented
 +   in a single HOST_WIDE_INT.  This function differs from the cst_fits
 +   versions in that the signedness of the type of cst is
 +   considered.  */
 +
 +static inline bool
 +tree_fits_shwi_p (const_tree cst)
 +{
 +  if (cst == NULL_TREE)
 +    return false;
 +
 +  if (TREE_CODE (cst) != INTEGER_CST)
 +    return false;
 +
 +  if (TREE_INT_CST_NUNITS (cst) != 1)
 +    return false;
 +
 +  if (TYPE_SIGN (TREE_TYPE (cst)) == SIGNED)
 +    return true;
 +
 +  if (TREE_INT_CST_ELT (cst, 0) >= 0)
 +    return true;
 +
 +  return false;
 +}
 +
 +/* Return true if T is an INTEGER_CST that can be manipulated
 +   efficiently on the host.  If SIGN is SIGNED, the value can be
 +   represented in a single HOST_WIDE_INT.  If SIGN is UNSIGNED, the
 +   value must be non-negative and can be represented in a single
 +   unsigned HOST_WIDE_INT.  */
 +
 +static inline bool
 +tree_fits_hwi_p (const_tree cst, signop sign)
 +{
 +  return sign ? tree_fits_uhwi_p (cst) : tree_fits_shwi_p (cst);
 +}
 +
 +/* Return true if T is an INTEGER_CST that can be manipulated
 +   efficiently on the host.  If the sign of CST is SIGNED, the value
 +   can be represented in a single HOST_WIDE_INT.  If the sign of CST
 +   is UNSIGNED, the value must be non-negative and can be represented
 +   in a single unsigned HOST_WIDE_INT.  */
 +
 +static inline bool
 +tree_fits_hwi_p (const_tree cst)
 +{
 +  if (cst == NULL_TREE)
 +    return false;
 +
 +  if (TREE_CODE (cst) != INTEGER_CST)
 +    return false;
 +
 +  return TYPE_UNSIGNED (TREE_TYPE (cst)) 
 +    ? tree_fits_uhwi_p (cst) : tree_fits_shwi_p (cst);
 +}
 +
 +/* Return the unsigned HOST_WIDE_INT least significant bits of CST.
 +   If checking is enabled, this ices if the value does not fit.  */
 +
 +static inline unsigned HOST_WIDE_INT
 +tree_to_uhwi (const_tree cst)
 +{
 +  gcc_checking_assert (tree_fits_uhwi_p (cst));
 +
 +  return (unsigned HOST_WIDE_INT)TREE_INT_CST_ELT (cst, 0);
 +}
 +
 +/* Return the HOST_WIDE_INT least significant bits of CST.  If
 +   checking is enabled, this ices if the value does not fit.  */
 +
 +static inline HOST_WIDE_INT
 +tree_to_shwi (const_tree cst)
 +{
 +  gcc_checking_assert (tree_fits_shwi_p (cst));
 +
 +  return (HOST_WIDE_INT)TREE_INT_CST_ELT (cst, 0);
 +}
 +
 +/* Return the HOST_WIDE_INT least significant bits of CST.  No
 +   checking is done to assure that it fits.  It is assumed that one of
 +   tree_fits_uhwi_p or tree_fits_shwi_p was done before this call. */
 +
 +static inline HOST_WIDE_INT
 +tree_to_hwi (const_tree cst)
 +{
 +  return TREE_INT_CST_ELT (cst, 0);
 +}
 +
 +/* Return the HOST_WIDE_INT least significant bits of CST.  The sign
 +   of the checking is based on SIGNOP. */
 +
 +static inline HOST_WIDE_INT
 +tree_to_hwi (const_tree cst, signop sgn)
 +{
 +  if (sgn == SIGNED)
 +    return tree_to_shwi (cst);
 +  else
 +    return tree_to_uhwi (cst);
 +}
 +
 +
  /* Compute the number of operands in an expression node NODE.  For
     tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
     otherwise it is looked up from the node's code.  */
@@@ -3387,6 -3211,8 +3405,8 @@@ tree_operand_check_code (const_tree __t
  #define complex_double_type_node      global_trees[TI_COMPLEX_DOUBLE_TYPE]
  #define complex_long_double_type_node global_trees[TI_COMPLEX_LONG_DOUBLE_TYPE]
  
+ #define pointer_bounds_type_node        global_trees[TI_POINTER_BOUNDS_TYPE]
  #define void_type_node                        global_trees[TI_VOID_TYPE]
  /* The C type `void *'.  */
  #define ptr_type_node                 global_trees[TI_PTR_TYPE]
  #define int128_integer_type_node      integer_types[itk_int128]
  #define int128_unsigned_type_node     integer_types[itk_unsigned_int128]
  
 -#define NULL_TREE (tree) NULL
 -
  /* True if NODE is an erroneous expression.  */
  
  #define error_operand_p(NODE)                                 \
@@@ -3547,9 -3375,9 +3567,9 @@@ extern hashval_t decl_assembler_name_ha
  
  extern size_t tree_size (const_tree);
  
 -/* Compute the number of bytes occupied by a tree with code CODE.  This
 -   function cannot be used for TREE_VEC codes, which are of variable
 -   length.  */
 +/* Compute the number of bytes occupied by a tree with code CODE.
 +   This function cannot be used for TREE_VEC or INTEGER_CST nodes,
 +   which are of variable length.  */
  extern size_t tree_code_size (enum tree_code);
  
  /* Allocate and return a new UID from the DECL_UID namespace.  */
@@@ -3579,12 -3407,6 +3599,12 @@@ extern tree build_case_label (tree, tre
  extern tree make_tree_binfo_stat (unsigned MEM_STAT_DECL);
  #define make_tree_binfo(t) make_tree_binfo_stat (t MEM_STAT_INFO)
  
 +/* Make a INTEGER_CST.  */
 +
 +extern tree make_int_cst_stat (int, int MEM_STAT_DECL);
 +#define make_int_cst(LEN, EXT_LEN) \
 +  make_int_cst_stat (LEN, EXT_LEN MEM_STAT_INFO)
 +
  /* Make a TREE_VEC.  */
  
  extern tree make_tree_vec_stat (int MEM_STAT_DECL);
@@@ -3701,18 -3523,27 +3721,18 @@@ extern tree build_var_debug_value_stat 
  
  /* Constructs double_int from tree CST.  */
  
 -static inline double_int
 -tree_to_double_int (const_tree cst)
 -{
 -  return TREE_INT_CST (cst);
 -}
 -
  extern tree double_int_to_tree (tree, double_int);
 -extern bool double_int_fits_to_tree_p (const_tree, double_int);
 -extern tree force_fit_type_double (tree, double_int, int, bool);
  
 -/* Create an INT_CST node with a CST value zero extended.  */
 +extern offset_int mem_ref_offset (const_tree);
 +extern tree wide_int_to_tree (tree type, const wide_int_ref &cst);
 +extern tree force_fit_type (tree, const wide_int_ref &, int, bool);
  
 -static inline tree
 -build_int_cstu (tree type, unsigned HOST_WIDE_INT cst)
 -{
 -  return double_int_to_tree (type, double_int::from_uhwi (cst));
 -}
 +/* Create an INT_CST node with a CST value zero extended.  */
  
 +/* static inline */
  extern tree build_int_cst (tree, HOST_WIDE_INT);
 +extern tree build_int_cstu (tree type, unsigned HOST_WIDE_INT cst);
  extern tree build_int_cst_type (tree, HOST_WIDE_INT);
 -extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
  extern tree make_vector_stat (unsigned MEM_STAT_DECL);
  #define make_vector(n) make_vector_stat (n MEM_STAT_INFO)
  extern tree build_vector_stat (tree, tree * MEM_STAT_DECL);
@@@ -3804,10 -3635,24 +3824,10 @@@ extern int attribute_list_contained (co
  extern int tree_int_cst_equal (const_tree, const_tree);
  extern int tree_int_cst_lt (const_tree, const_tree);
  extern int tree_int_cst_compare (const_tree, const_tree);
 -extern int host_integerp (const_tree, int)
 -#ifndef ENABLE_TREE_CHECKING
 -  ATTRIBUTE_PURE /* host_integerp is pure only when checking is disabled.  */
 -#endif
 -  ;
 -extern HOST_WIDE_INT tree_low_cst (const_tree, int);
 -#if !defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 4003)
 -extern inline __attribute__ ((__gnu_inline__)) HOST_WIDE_INT
 -tree_low_cst (const_tree t, int pos)
 -{
 -  gcc_assert (host_integerp (t, pos));
 -  return TREE_INT_CST_LOW (t);
 -}
 -#endif
  extern HOST_WIDE_INT size_low_cst (const_tree);
  extern int tree_int_cst_sgn (const_tree);
  extern int tree_int_cst_sign_bit (const_tree);
 -extern unsigned int tree_int_cst_min_precision (tree, bool);
 +extern unsigned int tree_int_cst_min_precision (tree, signop);
  extern bool tree_expr_nonnegative_p (tree);
  extern bool tree_expr_nonnegative_warnv_p (tree, bool *);
  extern bool may_negate_without_overflow_p (const_tree);
@@@ -4155,6 -4000,7 +4175,6 @@@ extern int integer_pow2p (const_tree)
  
  extern int integer_nonzerop (const_tree);
  
 -extern bool cst_and_fits_in_hwi (const_tree);
  extern tree num_ending_zeros (const_tree);
  
  /* fixed_zerop (tree x) is nonzero if X is a fixed-point constant of
@@@ -4577,9 -4423,10 +4597,9 @@@ extern tree fold_indirect_ref_loc (loca
  extern tree build_simple_mem_ref_loc (location_t, tree);
  #define build_simple_mem_ref(T)\
        build_simple_mem_ref_loc (UNKNOWN_LOCATION, T)
 -extern double_int mem_ref_offset (const_tree);
  extern tree build_invariant_address (tree, tree, HOST_WIDE_INT);
  extern tree constant_boolean_node (bool, tree);
 -extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
 +extern tree div_if_zero_remainder (const_tree, const_tree);
  
  extern bool tree_swap_operands_p (const_tree, const_tree, bool);
  extern enum tree_code swap_tree_comparison (enum tree_code);
@@@ -4681,8 -4528,6 +4701,6 @@@ extern tree build_call_expr_loc (locati
  extern tree build_call_expr (tree, int, ...);
  extern tree mathfn_built_in (tree, enum built_in_function fn);
  extern tree c_strlen (tree, int);
- extern tree std_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
- extern tree build_va_arg_indirect_ref (tree);
  extern tree build_string_literal (int, const char *);
  extern bool validate_arglist (const_tree, ...);
  extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
@@@ -4719,6 -4564,7 +4737,7 @@@ extern void get_type_static_bounds (con
  extern bool variably_modified_type_p (tree, tree);
  extern int tree_log2 (const_tree);
  extern int tree_floor_log2 (const_tree);
+ extern unsigned int tree_ctz (const_tree);
  extern int simple_cst_equal (const_tree, const_tree);
  extern hashval_t iterative_hash_expr (const_tree, hashval_t);
  extern hashval_t iterative_hash_exprs_commutative (const_tree,
@@@ -4867,7 -4713,7 +4886,7 @@@ extern tree get_attribute_namespace (co
  extern void apply_tm_attr (tree, tree);
  
  /* In stor-layout.c */
 -extern void set_min_and_max_values_for_integral_type (tree, int, bool);
 +extern void set_min_and_max_values_for_integral_type (tree, int, signop);
  extern void fixup_signed_type (tree);
  extern void internal_reference_types (void);
  extern unsigned int update_alignment_for_field (record_layout_info, tree,
@@@ -5235,146 -5081,5 +5254,146 @@@ may_be_aliased (const_tree var
  #endif        /* NO_DOLLAR_IN_LABEL */
  #endif        /* NO_DOT_IN_LABEL */
  
 +/* The tree and const_tree overload templates.   */
 +namespace wi
 +{
 +  template <>
 +  struct int_traits <const_tree>
 +  {
 +    static const enum precision_type precision_type = VAR_PRECISION;
 +    static const bool host_dependent_precision = false;
 +    static const bool is_sign_extended = false;
 +    static unsigned int get_precision (const_tree);
 +    static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int,
 +                                    const_tree);
 +  };
 +
 +  template <>
 +  struct int_traits <tree> : public int_traits <const_tree> {};
 +
 +  template <int N>
 +  class extended_tree
 +  {
 +  private:
 +    const_tree m_t;
 +
 +  public:
 +    extended_tree (const_tree);
 +
 +    unsigned int get_precision () const;
 +    const HOST_WIDE_INT *get_val () const;
 +    unsigned int get_len () const;
 +  };
 +
 +  template <>
 +  template <int N>
 +  struct int_traits <extended_tree <N> >
 +  {
 +    static const enum precision_type precision_type = CONST_PRECISION;
 +    static const bool host_dependent_precision = false;
 +    static const bool is_sign_extended = true;
 +    static const unsigned int precision = N;
 +  };
 +
 +  generic_wide_int <extended_tree <MAX_BITSIZE_MODE_ANY_INT> >
 +  to_widest (const_tree);
 +
 +  generic_wide_int <extended_tree <ADDR_MAX_PRECISION> > to_offset (const_tree);
 +}
 +
 +inline unsigned int
 +wi::int_traits <const_tree>::get_precision (const_tree tcst)
 +{
 +  return TYPE_PRECISION (TREE_TYPE (tcst));
 +}
 +
 +/* Convert the tree_cst X into a wide_int of PRECISION.  */
 +inline wi::storage_ref
 +wi::int_traits <const_tree>::decompose (HOST_WIDE_INT *,
 +                                      unsigned int precision, const_tree x)
 +{
 +  return wi::storage_ref (&TREE_INT_CST_ELT (x, 0), TREE_INT_CST_NUNITS (x),
 +                        precision);
 +}
 +
 +inline generic_wide_int <wi::extended_tree <MAX_BITSIZE_MODE_ANY_INT> >
 +wi::to_widest (const_tree t)
 +{
 +  return t;
 +}
 +
 +inline generic_wide_int <wi::extended_tree <ADDR_MAX_PRECISION> >
 +wi::to_offset (const_tree t)
 +{
 +  return t;
 +}
 +
 +template <int N>
 +inline wi::extended_tree <N>::extended_tree (const_tree t)
 +  : m_t (t)
 +{
 +  gcc_checking_assert (TYPE_PRECISION (TREE_TYPE (t)) <= N);
 +}
 +
 +template <int N>
 +inline unsigned int
 +wi::extended_tree <N>::get_precision () const
 +{
 +  return N;
 +}
 +
 +template <int N>
 +inline const HOST_WIDE_INT *
 +wi::extended_tree <N>::get_val () const
 +{
 +  return &TREE_INT_CST_ELT (m_t, 0);
 +}
 +
 +template <int N>
 +inline unsigned int
 +wi::extended_tree <N>::get_len () const
 +{
 +  if (N == MAX_BITSIZE_MODE_ANY_INT
 +      || N > TYPE_PRECISION (TREE_TYPE (m_t)))
 +    return TREE_INT_CST_EXT_NUNITS (m_t);
 +  else
 +    return TREE_INT_CST_NUNITS (m_t);
 +}
 +
 +namespace wi
 +{
 +  template <typename T>
 +  bool fits_to_tree_p (const T &x, const_tree);
 +
 +  wide_int min_value (const_tree);
 +  wide_int max_value (const_tree);
 +  wide_int from_mpz (const_tree, mpz_t, bool);
 +}
 +
 +template <typename T>
 +bool
 +wi::fits_to_tree_p (const T &x, const_tree type)
 +{
 +  if (TYPE_SIGN (type) == UNSIGNED)
 +    return eq_p (x, zext (x, TYPE_PRECISION (type)));
 +  else
 +    return eq_p (x, sext (x, TYPE_PRECISION (type)));
 +}
 +
 +/* Produce the smallest number that is represented in TYPE.  The precision
 +   and sign are taken from TYPE.  */
 +inline wide_int
 +wi::min_value (const_tree type)
 +{
 +  return min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
 +}
 +
 +/* Produce the largest number that is represented in TYPE.  The precision
 +   and sign are taken from TYPE.  */
 +inline wide_int
 +wi::max_value (const_tree type)
 +{
 +  return max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
 +}
  
  #endif  /* GCC_TREE_H  */
diff --combined gcc/tsan.c
index 6ddacfe3c942cca833b8a77e074759eb14b298c9,bceb5979de1578760c22a099849b2125bd264726..d273f168cefa5de9a9a633cbceb0a2714655976f
@@@ -28,14 -28,16 +28,16 @@@ along with GCC; see the file COPYING3
  #include "basic-block.h"
  #include "gimple.h"
  #include "function.h"
- #include "tree-ssa.h"
+ #include "gimple-ssa.h"
+ #include "cgraph.h"
+ #include "tree-cfg.h"
+ #include "tree-ssanames.h"
  #include "tree-pass.h"
  #include "tree-iterator.h"
  #include "langhooks.h"
  #include "output.h"
  #include "options.h"
  #include "target.h"
- #include "cgraph.h"
  #include "diagnostic.h"
  #include "tree-ssa-propagate.h"
  #include "tsan.h"
@@@ -443,8 -445,8 +445,8 @@@ instrument_builtin_call (gimple_stmt_it
          case check_last:
          case fetch_op:
            last_arg = gimple_call_arg (stmt, num - 1);
 -          if (!host_integerp (last_arg, 1)
 -              || (unsigned HOST_WIDE_INT) tree_low_cst (last_arg, 1)
 +          if (!tree_fits_uhwi_p (last_arg)
 +              || (unsigned HOST_WIDE_INT) tree_to_uhwi (last_arg)
                   > MEMMODEL_SEQ_CST)
              return;
            gimple_call_set_fndecl (stmt, decl);
            gcc_assert (num == 6);
            for (j = 0; j < 6; j++)
              args[j] = gimple_call_arg (stmt, j);
 -          if (!host_integerp (args[4], 1)
 -              || (unsigned HOST_WIDE_INT) tree_low_cst (args[4], 1)
 +          if (!tree_fits_uhwi_p (args[4])
 +              || (unsigned HOST_WIDE_INT) tree_to_uhwi (args[4])
                   > MEMMODEL_SEQ_CST)
              return;
 -          if (!host_integerp (args[5], 1)
 -              || (unsigned HOST_WIDE_INT) tree_low_cst (args[5], 1)
 +          if (!tree_fits_uhwi_p (args[5])
 +              || (unsigned HOST_WIDE_INT) tree_to_uhwi (args[5])
                   > MEMMODEL_SEQ_CST)
              return;
            update_gimple_call (gsi, decl, 5, args[0], args[1], args[2],
diff --combined gcc/value-prof.c
index 29f51e7457acb6a5e8da5948c25a0323fcd71a29,0a9388285bb69b6515d76888f7b9155404b114dc..71766093367dde4831e253117b37378a1cdf95a1
@@@ -21,6 -21,7 +21,7 @@@ along with GCC; see the file COPYING3
  #include "system.h"
  #include "coretypes.h"
  #include "tm.h"
+ #include "tree.h"
  #include "rtl.h"
  #include "expr.h"
  #include "hard-reg-set.h"
  #include "optabs.h"
  #include "regs.h"
  #include "ggc.h"
- #include "tree-ssa.h"
+ #include "gimple.h"
+ #include "gimple-ssa.h"
+ #include "tree-cfg.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
+ #include "tree-ssanames.h"
  #include "diagnostic.h"
  #include "gimple-pretty-print.h"
  #include "coverage.h"
  #include "tree.h"
  #include "gcov-io.h"
- #include "cgraph.h"
  #include "timevar.h"
  #include "dumpfile.h"
  #include "pointer-set.h"
@@@ -806,17 -811,9 +811,17 @@@ gimple_divmod_fixed_value_transform (gi
    else
      prob = 0;
  
 -  tree_val = build_int_cst_wide (get_gcov_type (),
 -                               (unsigned HOST_WIDE_INT) val,
 -                               val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
 +  if (sizeof (gcov_type) == sizeof (HOST_WIDE_INT))
 +    tree_val = build_int_cst (get_gcov_type (), val);
 +  else
 +    {
 +      HOST_WIDE_INT a[2];
 +      a[0] = (unsigned HOST_WIDE_INT) val;
 +      a[1] = val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1;
 +      
 +      tree_val = wide_int_to_tree (get_gcov_type (), wide_int::from_array (a, 2,
 +      TYPE_PRECISION (get_gcov_type ()), false));
 +    }
    result = gimple_divmod_fixed_value (stmt, tree_val, prob, count, all);
  
    if (dump_file)
@@@ -1211,9 -1208,9 +1216,9 @@@ init_node_map (bool local
                           " with nodes %s/%i %s/%i\n",
                           n->profile_id,
                           cgraph_node_name (n),
-                          n->symbol.order,
-                          symtab_node_name (*(symtab_node*)val),
-                          (*(symtab_node *)val)->symbol.order);
+                          n->order,
+                          symtab_node_name (*(symtab_node **)val),
+                          (*(symtab_node **)val)->order);
                n->profile_id = (n->profile_id + 1) & 0x7fffffff;
              }
          }
                       "Node %s/%i has no profile-id"
                       " (profile feedback missing?)\n",
                       cgraph_node_name (n),
-                      n->symbol.order);
+                      n->order);
            continue;
          }
        else if ((val = pointer_map_contains (cgraph_node_map,
                       "Node %s/%i has IP profile-id %i conflict. "
                       "Giving up.\n",
                       cgraph_node_name (n),
-                      n->symbol.order,
+                      n->order,
                       n->profile_id);
            *val = NULL;
            continue;
@@@ -1276,7 -1273,7 +1281,7 @@@ static boo
  check_ic_target (gimple call_stmt, struct cgraph_node *target)
  {
     location_t locus;
-    if (gimple_check_call_matching_types (call_stmt, target->symbol.decl, true))
+    if (gimple_check_call_matching_types (call_stmt, target->decl, true))
       return true;
  
     locus =  gimple_location (call_stmt);
@@@ -1319,7 -1316,7 +1324,7 @@@ gimple_ic (gimple icall_stmt, struct cg
    load_stmt = gimple_build_assign (tmp0, tmp);
    gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
  
-   tmp = fold_convert (optype, build_addr (direct_call->symbol.decl,
+   tmp = fold_convert (optype, build_addr (direct_call->decl,
                                          current_function_decl));
    load_stmt = gimple_build_assign (tmp1, tmp);
    gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
    gimple_set_vuse (icall_stmt, NULL_TREE);
    update_stmt (icall_stmt);
    dcall_stmt = gimple_copy (icall_stmt);
-   gimple_call_set_fndecl (dcall_stmt, direct_call->symbol.decl);
-   dflags = flags_from_decl_or_type (direct_call->symbol.decl);
+   gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
+   dflags = flags_from_decl_or_type (direct_call->decl);
    if ((dflags & ECF_NORETURN) != 0)
      gimple_call_set_lhs (dcall_stmt, NULL_TREE);
    gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT);
@@@ -1497,7 -1494,7 +1502,7 @@@ gimple_ic_transform (gimple_stmt_iterat
          fprintf (dump_file, "Indirect call -> direct call ");
          print_generic_expr (dump_file, gimple_call_fn (stmt), TDF_SLIM);
          fprintf (dump_file, "=> ");
-         print_generic_expr (dump_file, direct_call->symbol.decl, TDF_SLIM);
+         print_generic_expr (dump_file, direct_call->decl, TDF_SLIM);
          fprintf (dump_file, " transformation skipped because of type mismatch");
          print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
        }
        fprintf (dump_file, "Indirect call -> direct call ");
        print_generic_expr (dump_file, gimple_call_fn (stmt), TDF_SLIM);
        fprintf (dump_file, "=> ");
-       print_generic_expr (dump_file, direct_call->symbol.decl, TDF_SLIM);
+       print_generic_expr (dump_file, direct_call->decl, TDF_SLIM);
        fprintf (dump_file, " transformation on insn postponned to ipa-profile");
        print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
        fprintf (dump_file, "hist->count "HOST_WIDEST_INT_PRINT_DEC
@@@ -1725,18 -1722,9 +1730,18 @@@ gimple_stringops_transform (gimple_stmt
      default:
        gcc_unreachable ();
      }
 -  tree_val = build_int_cst_wide (get_gcov_type (),
 -                               (unsigned HOST_WIDE_INT) val,
 -                               val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1);
 +  if (sizeof (gcov_type) == sizeof (HOST_WIDE_INT))
 +    tree_val = build_int_cst (get_gcov_type (), val);
 +  else
 +    {
 +      HOST_WIDE_INT a[2];
 +      a[0] = (unsigned HOST_WIDE_INT) val;
 +      a[1] = val >> (HOST_BITS_PER_WIDE_INT - 1) >> 1;
 +      
 +      tree_val = wide_int_to_tree (get_gcov_type (), wide_int::from_array (a, 2,
 +      TYPE_PRECISION (get_gcov_type ()), false));
 +    }
 +
    if (dump_file)
      {
        fprintf (dump_file, "Single value %i stringop transformation on ",
diff --combined gcc/var-tracking.c
index 89c53efc95a77bde8094740994859cb1b57c75bb,8b07f9fbf9f123cff0ce5f3c0fdc3714c6a97e85..eb3f7ce3a7d2206c4a6a72c6de27474498f1224a
  #include "regs.h"
  #include "expr.h"
  #include "tree-pass.h"
+ #include "bitmap.h"
+ #include "tree-dfa.h"
  #include "tree-ssa.h"
  #include "cselib.h"
  #include "target.h"
@@@ -3525,23 -3527,6 +3527,23 @@@ loc_cmp (rtx x, rtx y
        default:
        gcc_unreachable ();
        }
 +  if (CONST_WIDE_INT_P (x))
 +    {
 +      /* Compare the vector length first.  */
 +      if (CONST_WIDE_INT_NUNITS (x) >= CONST_WIDE_INT_NUNITS (y))
 +      return 1;
 +      else if (CONST_WIDE_INT_NUNITS (x) < CONST_WIDE_INT_NUNITS (y))
 +      return -1;
 +
 +      /* Compare the vectors elements.  */;
 +      for (j = CONST_WIDE_INT_NUNITS (x) - 1; j >= 0 ; j--)
 +      {
 +        if (CONST_WIDE_INT_ELT (x, j) < CONST_WIDE_INT_ELT (y, j))
 +          return -1;
 +        if (CONST_WIDE_INT_ELT (x, j) > CONST_WIDE_INT_ELT (y, j))
 +          return 1;
 +      }
 +    }
  
    return 0;
  }
@@@ -6305,9 -6290,9 +6307,9 @@@ prepare_call_arguments (basic_block bb
                          && DECL_INITIAL (SYMBOL_REF_DECL (l->loc)))
                        {
                          initial = DECL_INITIAL (SYMBOL_REF_DECL (l->loc));
 -                        if (host_integerp (initial, 0))
 +                        if (tree_fits_shwi_p (initial))
                            {
 -                            item = GEN_INT (tree_low_cst (initial, 0));
 +                            item = GEN_INT (tree_to_shwi (initial));
                              item = gen_rtx_CONCAT (indmode, mem, item);
                              call_arguments
                                = gen_rtx_EXPR_LIST (VOIDmode, item,
        = TYPE_MODE (TREE_TYPE (OBJ_TYPE_REF_EXPR (obj_type_ref)));
        rtx clobbered = gen_rtx_MEM (mode, this_arg);
        HOST_WIDE_INT token
 -      = tree_low_cst (OBJ_TYPE_REF_TOKEN (obj_type_ref), 0);
 +      = tree_to_shwi (OBJ_TYPE_REF_TOKEN (obj_type_ref));
        if (token)
        clobbered = plus_constant (mode, clobbered,
                                   token * GET_MODE_SIZE (mode));
@@@ -7922,7 -7907,7 +7924,7 @@@ struct expand_loc_callback_dat
  
    /* Stack of values and debug_exprs under expansion, and their
       children.  */
-   vec<rtx, va_stack> expanding;
+   stack_vec<rtx, 4> expanding;
  
    /* Stack of values and debug_exprs whose expansion hit recursion
       cycles.  They will have VALUE_RECURSED_INTO marked when added to
       resolves to a valid location.  So, if the flag remains set at the
       end of the search, we know no valid location for this one can
       possibly exist.  */
-   vec<rtx, va_stack> pending;
+   stack_vec<rtx, 4> pending;
  
    /* The maximum depth among the sub-expressions under expansion.
       Zero indicates no expansion so far.  */
@@@ -8432,11 -8417,11 +8434,11 @@@ vt_expand_loc_callback (rtx x, bitmap r
     This function performs this finalization of NULL locations.  */
  
  static void
- resolve_expansions_pending_recursion (vec<rtx, va_stack> pending)
+ resolve_expansions_pending_recursion (vec<rtx, va_heap> *pending)
  {
-   while (!pending.is_empty ())
+   while (!pending->is_empty ())
      {
-       rtx x = pending.pop ();
+       rtx x = pending->pop ();
        decl_or_value dv;
  
        if (!VALUE_RECURSED_INTO (x))
    do                                                          \
      {                                                         \
        (d).vars = (v);                                         \
-       vec_stack_alloc (rtx, (d).expanding, 4);                        \
-       vec_stack_alloc (rtx, (d).pending, 4);                  \
        (d).depth.complexity = (d).depth.entryvals = 0;         \
      }                                                         \
    while (0)
  #define FINI_ELCD(d, l)                                               \
    do                                                          \
      {                                                         \
-       resolve_expansions_pending_recursion ((d).pending);     \
+       resolve_expansions_pending_recursion (&(d).pending);    \
        (d).pending.release ();                                 \
        (d).expanding.release ();                                       \
                                                                \
@@@ -8684,7 -8667,7 +8684,7 @@@ emit_note_insn_var_location (variable_d
        ++n_var_parts;
      }
    type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (decl));
 -  if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
 +  if ((unsigned HOST_WIDE_INT) last_limit < tree_to_uhwi (type_size_unit))
      complete = false;
  
    if (! flag_var_tracking_uninit)
  
  int
  var_track_values_to_stack (variable_def **slot,
-                          vec<rtx, va_stack> *changed_values_stack)
+                          vec<rtx, va_heap> *changed_values_stack)
  {
    variable var = *slot;
  
@@@ -8794,7 -8777,7 +8794,7 @@@ remove_value_from_changed_variables (rt
  
  static void
  notify_dependents_of_changed_value (rtx val, variable_table_type htab,
-                                   vec<rtx, va_stack> *changed_values_stack)
+                                   vec<rtx, va_heap> *changed_values_stack)
  {
    variable_def **slot;
    variable var;
@@@ -8879,13 -8862,11 +8879,11 @@@ process_changed_values (variable_table_
  {
    int i, n;
    rtx val;
-   vec<rtx, va_stack> changed_values_stack;
-   vec_stack_alloc (rtx, changed_values_stack, 20);
+   stack_vec<rtx, 20> changed_values_stack;
  
    /* Move values from changed_variables to changed_values_stack.  */
    changed_variables
-     .traverse <vec<rtx, va_stack>*, var_track_values_to_stack>
+     .traverse <vec<rtx, va_heap>*, var_track_values_to_stack>
        (&changed_values_stack);
  
    /* Back-propagate change notifications in values while popping
          n--;
        }
      }
-   changed_values_stack.release ();
  }
  
  /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
diff --combined gcc/varasm.c
index 2ad6b4488ab502c6b7843ad68b24beddea2f46ad,beafb558c9cc50b06429ac3470e132215a9197a5..1f772c7a398afc9701dcde7cbf293db13c9e71e4
@@@ -46,7 -46,6 +46,6 @@@ along with GCC; see the file COPYING3
  #include "target.h"
  #include "common/common-target.h"
  #include "targhooks.h"
- #include "tree-mudflap.h"
  #include "cgraph.h"
  #include "pointer-set.h"
  #include "asan.h"
@@@ -1137,7 -1136,7 +1136,7 @@@ get_block_for_decl (tree decl
       constant size.  */
    if (DECL_SIZE_UNIT (decl) == NULL)
      return NULL;
 -  if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
 +  if (!tree_fits_uhwi_p (DECL_SIZE_UNIT (decl)))
      return NULL;
  
    /* Find out which section should contain DECL.  We cannot put it into
@@@ -1247,10 -1246,6 +1246,6 @@@ make_decl_rtl (tree decl
          && SYMBOL_REF_HAS_BLOCK_INFO_P (XEXP (x, 0)))
        change_symbol_block (XEXP (x, 0), get_block_for_decl (decl));
  
-       /* Make this function static known to the mudflap runtime.  */
-       if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
-       mudflap_enqueue_decl (decl);
        return;
      }
  
       If the name is changed, the macro ASM_OUTPUT_LABELREF
       will have to know how to strip this information.  */
    targetm.encode_section_info (decl, DECL_RTL (decl), true);
-   /* Make this function static known to the mudflap runtime.  */
-   if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
-     mudflap_enqueue_decl (decl);
  }
  
  /* Like make_decl_rtl, but inhibit creation of new alias sets when
  rtx
  make_decl_rtl_for_debug (tree decl)
  {
-   unsigned int save_aliasing_flag, save_mudflap_flag;
+   unsigned int save_aliasing_flag;
    rtx rtl;
  
    if (DECL_RTL_SET_P (decl))
       we do not want to create alias sets that will throw the alias
       numbers off in the comparison dumps.  So... clearing
       flag_strict_aliasing will keep new_alias_set() from creating a
-      new set.  It is undesirable to register decl with mudflap
-      in this case as well.  */
+      new set.  */
    save_aliasing_flag = flag_strict_aliasing;
    flag_strict_aliasing = 0;
-   save_mudflap_flag = flag_mudflap;
-   flag_mudflap = 0;
  
    rtl = DECL_RTL (decl);
    /* Reset DECL_RTL back, as various parts of the compiler expects
    SET_DECL_RTL (decl, NULL);
  
    flag_strict_aliasing = save_aliasing_flag;
-   flag_mudflap = save_mudflap_flag;
    return rtl;
  }
  \f
@@@ -1903,7 -1889,7 +1889,7 @@@ assemble_noswitch_variable (tree decl, 
  {
    unsigned HOST_WIDE_INT size, rounded;
  
 -  size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
 +  size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
    rounded = size;
  
    if ((flag_sanitize & SANITIZE_ADDRESS) && asan_protect_global (decl))
@@@ -1950,11 -1936,11 +1936,11 @@@ assemble_variable_contents (tree decl, 
          && !initializer_zerop (DECL_INITIAL (decl)))
        /* Output the actual data.  */
        output_constant (DECL_INITIAL (decl),
 -                       tree_low_cst (DECL_SIZE_UNIT (decl), 1),
 +                       tree_to_uhwi (DECL_SIZE_UNIT (decl)),
                         get_variable_align (decl));
        else
        /* Leave space for it.  */
 -      assemble_zeros (tree_low_cst (DECL_SIZE_UNIT (decl), 1));
 +      assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
      }
  }
  
@@@ -2140,7 -2126,7 +2126,7 @@@ assemble_variable (tree decl, int top_l
        if (asan_protected)
        {
          unsigned HOST_WIDE_INT int size
 -          = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
 +          = tree_to_uhwi (DECL_SIZE_UNIT (decl));
          assemble_zeros (asan_red_zone_size (size));
        }
      }
@@@ -2371,7 -2357,7 +2357,7 @@@ mark_decl_referenced (tree decl
         definition.  */
        struct cgraph_node *node = cgraph_get_create_node (decl);
        if (!DECL_EXTERNAL (decl)
-         && !node->symbol.definition)
+         && !node->definition)
        cgraph_mark_force_output_node (node);
      }
    else if (TREE_CODE (decl) == VAR_DECL)
        struct varpool_node *node = varpool_node_for_decl (decl);
        /* C++ frontend use mark_decl_references to force COMDAT variables
           to be output that might appear dead otherwise.  */
-       node->symbol.force_output = true;
+       node->force_output = true;
      }
    /* else do nothing - we can get various sorts of CST nodes here,
       which do not need to be marked.  */
@@@ -2723,7 -2709,7 +2709,7 @@@ decode_addr_const (tree exp, struct add
    while (1)
      {
        if (TREE_CODE (target) == COMPONENT_REF
 -        && host_integerp (byte_position (TREE_OPERAND (target, 1)), 0))
 +        && tree_fits_shwi_p (byte_position (TREE_OPERAND (target, 1))))
        {
          offset += int_byte_position (TREE_OPERAND (target, 1));
          target = TREE_OPERAND (target, 0);
        else if (TREE_CODE (target) == ARRAY_REF
               || TREE_CODE (target) == ARRAY_RANGE_REF)
        {
 -        offset += (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (target)), 1)
 -                   * tree_low_cst (TREE_OPERAND (target, 1), 0));
 +        offset += (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (target)))
 +                   * tree_to_shwi (TREE_OPERAND (target, 1)));
          target = TREE_OPERAND (target, 0);
        }
        else if (TREE_CODE (target) == MEM_REF
               && TREE_CODE (TREE_OPERAND (target, 0)) == ADDR_EXPR)
        {
 -        offset += mem_ref_offset (target).low;
 +        offset += mem_ref_offset (target).to_short_addr ();
          target = TREE_OPERAND (TREE_OPERAND (target, 0), 0);
        }
        else if (TREE_CODE (target) == INDIRECT_REF
@@@ -2818,8 -2804,8 +2804,8 @@@ const_hash_1 (const tree exp
    switch (code)
      {
      case INTEGER_CST:
 -      p = (char *) &TREE_INT_CST (exp);
 -      len = sizeof TREE_INT_CST (exp);
 +      p = (char *) &TREE_INT_CST_ELT (exp, 0);
 +      len = TREE_INT_CST_NUNITS (exp) * sizeof (HOST_WIDE_INT);
        break;
  
      case REAL_CST:
@@@ -3206,10 -3192,6 +3192,6 @@@ build_constant_desc (tree exp
    desc = ggc_alloc_constant_descriptor_tree ();
    desc->value = copy_constant (exp);
  
-   /* Propagate marked-ness to copied constant.  */
-   if (flag_mudflap && mf_marked_p (exp))
-     mf_mark (desc->value);
    /* Create a string containing the label name, in LABEL.  */
    labelno = const_labelno++;
    ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
@@@ -3405,8 -3387,6 +3387,6 @@@ output_constant_def_contents (rtx symbo
          assemble_zeros (asan_red_zone_size (size));
        }
      }
-   if (flag_mudflap)
-     mudflap_enqueue_constant (exp);
  }
  
  /* Look up EXP in the table of constant descriptors.  Return the rtl
@@@ -3526,7 -3506,6 +3506,7 @@@ const_rtx_hash_1 (rtx *xp, void *data
    enum rtx_code code;
    hashval_t h, *hp;
    rtx x;
 +  int i;
  
    x = *xp;
    code = GET_CODE (x);
      {
      case CONST_INT:
        hwi = INTVAL (x);
 +
      fold_hwi:
        {
        int shift = sizeof (hashval_t) * CHAR_BIT;
        const int n = sizeof (HOST_WIDE_INT) / sizeof (hashval_t);
 -      int i;
 -
 +      
        h ^= (hashval_t) hwi;
        for (i = 1; i < n; ++i)
          {
        }
        break;
  
 +    case CONST_WIDE_INT:
 +      hwi = GET_MODE_PRECISION (mode);
 +      {
 +      for (i = 0; i < CONST_WIDE_INT_NUNITS (x); i++)
 +        hwi ^= CONST_WIDE_INT_ELT (x, i);
 +      goto fold_hwi;
 +      }
 +
      case CONST_DOUBLE:
 -      if (mode == VOIDmode)
 +      if (TARGET_SUPPORTS_WIDE_INT == 0 && mode == VOIDmode)
        {
          hwi = CONST_DOUBLE_LOW (x) ^ CONST_DOUBLE_HIGH (x);
          goto fold_hwi;
@@@ -4652,7 -4623,8 +4632,7 @@@ output_constant (tree exp, unsigned HOS
        exp = build1 (ADDR_EXPR, saved_type, TREE_OPERAND (exp, 0));
        /* Likewise for constant ints.  */
        else if (TREE_CODE (exp) == INTEGER_CST)
 -      exp = build_int_cst_wide (saved_type, TREE_INT_CST_LOW (exp),
 -                                TREE_INT_CST_HIGH (exp));
 +      exp = wide_int_to_tree (saved_type, exp);
  
      }
  
    if (TREE_CODE (exp) == FDESC_EXPR)
      {
  #ifdef ASM_OUTPUT_FDESC
 -      HOST_WIDE_INT part = tree_low_cst (TREE_OPERAND (exp, 1), 0);
 +      HOST_WIDE_INT part = tree_to_shwi (TREE_OPERAND (exp, 1));
        tree decl = TREE_OPERAND (exp, 0);
        ASM_OUTPUT_FDESC (asm_out_file, decl, part);
  #else
      case REFERENCE_TYPE:
      case OFFSET_TYPE:
      case FIXED_POINT_TYPE:
+     case POINTER_BOUNDS_TYPE:
        if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
                                           EXPAND_INITIALIZER),
                              MIN (size, thissize), align, 0))
@@@ -4790,7 -4763,7 +4771,7 @@@ array_size_for_constructor (tree val
    tree max_index;
    unsigned HOST_WIDE_INT cnt;
    tree index, value, tmp;
 -  double_int i;
 +  offset_int i;
  
    /* This code used to attempt to handle string constants that are not
       arrays of single-bytes, but nothing else does, so there's no point in
  
    /* Compute the total number of array elements.  */
    tmp = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)));
 -  i = tree_to_double_int (max_index) - tree_to_double_int (tmp);
 -  i += double_int_one;
 +  i = wi::to_offset (max_index) - wi::to_offset (tmp) + 1;
  
    /* Multiply by the array element unit size to find number of bytes.  */
 -  i *= tree_to_double_int (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
 +  i *= wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
  
 -  gcc_assert (i.fits_uhwi ());
 -  return i.low;
 +  gcc_assert (wi::fits_uhwi_p (i));
 +  return i.to_uhwi ();
  }
  
  /* Other datastructures + helpers for output_constructor.  */
@@@ -4858,9 -4832,9 +4839,9 @@@ output_constructor_array_range (oc_loca
      = int_size_in_bytes (TREE_TYPE (local->type));
  
    HOST_WIDE_INT lo_index
 -    = tree_low_cst (TREE_OPERAND (local->index, 0), 0);
 +    = tree_to_shwi (TREE_OPERAND (local->index, 0));
    HOST_WIDE_INT hi_index
 -    = tree_low_cst (TREE_OPERAND (local->index, 1), 0);
 +    = tree_to_shwi (TREE_OPERAND (local->index, 1));
    HOST_WIDE_INT index;
  
    unsigned int align2
@@@ -4898,10 -4872,11 +4879,10 @@@ output_constructor_regular_field (oc_lo
         sign-extend the result because Ada has negative DECL_FIELD_OFFSETs
         but we are using an unsigned sizetype.  */
        unsigned prec = TYPE_PRECISION (sizetype);
 -      double_int idx = tree_to_double_int (local->index)
 -                     - tree_to_double_int (local->min_index);
 -      idx = idx.sext (prec);
 -      fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
 -                * idx.low);
 +      offset_int idx = wi::sext (wi::to_offset (local->index)
 +                               - wi::to_offset (local->min_index), prec);
 +      fieldpos = (idx * wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (local->val))))
 +      .to_shwi ();
      }
    else if (local->field != NULL_TREE)
      fieldpos = int_byte_position (local->field);
          gcc_assert (!fieldsize || !DECL_CHAIN (local->field));
        }
        else
 -      fieldsize = tree_low_cst (DECL_SIZE_UNIT (local->field), 1);
 +      fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));
      }
    else
      fieldsize = int_size_in_bytes (TREE_TYPE (local->type));
@@@ -4975,15 -4950,15 +4956,15 @@@ output_constructor_bitfield (oc_local_s
    /* Bit size of this element.  */
    HOST_WIDE_INT ebitsize
      = (local->field
 -       ? tree_low_cst (DECL_SIZE (local->field), 1)
 -       : tree_low_cst (TYPE_SIZE (TREE_TYPE (local->type)), 1));
 +       ? tree_to_uhwi (DECL_SIZE (local->field))
 +       : tree_to_uhwi (TYPE_SIZE (TREE_TYPE (local->type))));
  
    /* Relative index of this element if this is an array component.  */
    HOST_WIDE_INT relative_index
      = (!local->field
         ? (local->index
 -        ? (tree_low_cst (local->index, 0)
 -           - tree_low_cst (local->min_index, 0))
 +        ? (tree_to_shwi (local->index)
 +           - tree_to_shwi (local->min_index))
          : local->last_relative_index + 1)
         : 0);
  
             the word boundary in the INTEGER_CST. We can
             only select bits from the LOW or HIGH part
             not from both.  */
 -        if (shift < HOST_BITS_PER_WIDE_INT
 -            && shift + this_time > HOST_BITS_PER_WIDE_INT)
 -          {
 -            this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
 -            shift = HOST_BITS_PER_WIDE_INT;
 -          }
 +        if ((shift / HOST_BITS_PER_WIDE_INT)
 +            != ((shift + this_time) / HOST_BITS_PER_WIDE_INT))
 +          this_time = (shift + this_time) & (HOST_BITS_PER_WIDE_INT - 1);
  
          /* Now get the bits from the appropriate constant word.  */
 -        if (shift < HOST_BITS_PER_WIDE_INT)
 -          value = TREE_INT_CST_LOW (local->val);
 -        else
 -          {
 -            gcc_assert (shift < HOST_BITS_PER_DOUBLE_INT);
 -            value = TREE_INT_CST_HIGH (local->val);
 -            shift -= HOST_BITS_PER_WIDE_INT;
 -          }
 +        value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
 +        shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
  
          /* Get the result. This works only when:
             1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
             the word boundary in the INTEGER_CST. We can
             only select bits from the LOW or HIGH part
             not from both.  */
 -        if (shift < HOST_BITS_PER_WIDE_INT
 -            && shift + this_time > HOST_BITS_PER_WIDE_INT)
 +        if ((shift / HOST_BITS_PER_WIDE_INT)
 +            != ((shift + this_time) / HOST_BITS_PER_WIDE_INT))
            this_time = (HOST_BITS_PER_WIDE_INT - shift);
  
          /* Now get the bits from the appropriate constant word.  */
 -        if (shift < HOST_BITS_PER_WIDE_INT)
 -          value = TREE_INT_CST_LOW (local->val);
 -        else
 -          {
 -            gcc_assert (shift < HOST_BITS_PER_DOUBLE_INT);
 -            value = TREE_INT_CST_HIGH (local->val);
 -            shift -= HOST_BITS_PER_WIDE_INT;
 -          }
 +        value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
 +        shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
  
          /* Get the result. This works only when:
             1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
@@@ -5392,9 -5382,9 +5373,9 @@@ weak_finish_1 (tree decl
  static tree
  find_decl (tree target)
  {
-   symtab_node node = symtab_node_for_asm (target);
+   symtab_node *node = symtab_node_for_asm (target);
    if (node)
-     return node->symbol.decl;
+     return node->decl;
    return NULL_TREE;
  }
  
@@@ -5679,9 -5669,9 +5660,9 @@@ assemble_alias (tree decl, tree target
  
    /* Allow aliases to aliases.  */
    if (TREE_CODE (decl) == FUNCTION_DECL)
-     cgraph_get_create_node (decl)->symbol.alias = true;
+     cgraph_get_create_node (decl)->alias = true;
    else
-     varpool_node_for_decl (decl)->symbol.alias = true;
+     varpool_node_for_decl (decl)->alias = true;
  
    /* If the target has already been emitted, we don't have to queue the
       alias.  This saves a tad of memory.  */
@@@ -5784,12 -5774,12 +5765,12 @@@ dump_tm_clone_pairs (vec<tm_alias_pair
         TM_GETTMCLONE.  If neither of these are true, we didn't generate
         a clone, and we didn't call it indirectly... no sense keeping it
         in the clone table.  */
-       if (!dst_n || !dst_n->symbol.definition)
+       if (!dst_n || !dst_n->definition)
        continue;
  
        /* This covers the case where we have optimized the original
         function away, and only access the transactional clone.  */
-       if (!src_n || !src_n->symbol.definition)
+       if (!src_n || !src_n->definition)
        continue;
  
        if (!switched)
@@@ -6284,9 -6274,8 +6265,8 @@@ categorize_decl_for_section (const_tre
      return SECCAT_TEXT;
    else if (TREE_CODE (decl) == STRING_CST)
      {
-       if (flag_mudflap
-         || ((flag_sanitize & SANITIZE_ADDRESS)
-             && asan_protect_global (CONST_CAST_TREE (decl))))
+       if ((flag_sanitize & SANITIZE_ADDRESS)
+         && asan_protect_global (CONST_CAST_TREE (decl)))
        /* or !flag_merge_constants */
          return SECCAT_RODATA;
        else
        }
        else if (reloc & targetm.asm_out.reloc_rw_mask ())
        ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO;
-       else if (reloc || flag_merge_constants < 2 || flag_mudflap
+       else if (reloc || flag_merge_constants < 2
               || ((flag_sanitize & SANITIZE_ADDRESS)
                   && asan_protect_global (CONST_CAST_TREE (decl))))
        /* C and C++ don't allow different variables to share the same
@@@ -6735,20 -6724,20 +6715,20 @@@ default_binds_local_p_1 (const_tree exp
        && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
      {
        struct varpool_node *vnode = varpool_get_node (exp);
-       if (vnode && resolution_local_p (vnode->symbol.resolution))
+       if (vnode && resolution_local_p (vnode->resolution))
        resolved_locally = true;
        if (vnode
-         && resolution_to_local_definition_p (vnode->symbol.resolution))
+         && resolution_to_local_definition_p (vnode->resolution))
        resolved_to_local_def = true;
      }
    else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
      {
        struct cgraph_node *node = cgraph_get_node (exp);
        if (node
-         && resolution_local_p (node->symbol.resolution))
+         && resolution_local_p (node->resolution))
        resolved_locally = true;
        if (node
-         && resolution_to_local_definition_p (node->symbol.resolution))
+         && resolution_to_local_definition_p (node->resolution))
        resolved_to_local_def = true;
      }
  
@@@ -6829,15 -6818,15 +6809,15 @@@ decl_binds_to_current_def_p (tree decl
      {
        struct varpool_node *vnode = varpool_get_node (decl);
        if (vnode
-         && vnode->symbol.resolution != LDPR_UNKNOWN)
-       return resolution_to_local_definition_p (vnode->symbol.resolution);
+         && vnode->resolution != LDPR_UNKNOWN)
+       return resolution_to_local_definition_p (vnode->resolution);
      }
    else if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        struct cgraph_node *node = cgraph_get_node (decl);
        if (node
-         && node->symbol.resolution != LDPR_UNKNOWN)
-       return resolution_to_local_definition_p (node->symbol.resolution);
+         && node->resolution != LDPR_UNKNOWN)
+       return resolution_to_local_definition_p (node->resolution);
      }
    /* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks
       binds locally but still can be overwritten), DECL_COMMON (can be merged
@@@ -7080,7 -7069,7 +7060,7 @@@ place_block_symbol (rtx symbol
      {
        decl = SYMBOL_REF_DECL (symbol);
        alignment = get_variable_align (decl);
 -      size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
 +      size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
        if ((flag_sanitize & SANITIZE_ADDRESS)
          && asan_protect_global (decl))
        {
@@@ -7246,7 -7235,7 +7226,7 @@@ output_object_block (struct object_bloc
          HOST_WIDE_INT size;
          decl = SYMBOL_REF_DECL (symbol);
          assemble_variable_contents (decl, XSTR (symbol, 0), false);
 -        size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
 +        size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
          offset += size;
          if ((flag_sanitize & SANITIZE_ADDRESS)
              && asan_protect_global (decl))