[PATCH][RFC] bitpacking rewrite

Richard Guenther rguenther@suse.de
Sat Jun 12 17:07:00 GMT 2010


On Sat, 12 Jun 2010, Richard Guenther wrote:

> On Sat, 12 Jun 2010, Richard Guenther wrote:
> 
> > 
> > The following preliminary patch rewrites bitpacking to happen
> > word-by-word and on the stack (well, in the preliminary form
> > only on the stack after inlining).
> > 
> > Comments?
> 
> Benchmarking it against WHOPR bootstrap WPA stage of cc1 shows
> 
>  ipa lto gimple I/O    :   2.05 ( 8%) usr   0.17 (20%) sys   2.11 ( 8%) 
> wall       0 kB ( 0%) ggc
>  ipa lto decl I/O      :   7.48 (29%) usr   0.16 (19%) sys   7.56 (28%) 
> wall  263472 kB (58%) ggc
> 
> unpatched vs.
> 
>  ipa lto gimple I/O    :   1.90 ( 7%) usr   0.10 (12%) sys   2.08 ( 8%) 
> wall       0 kB ( 0%) ggc
>  ipa lto decl I/O      :   6.82 (27%) usr   0.10 (12%) sys   6.91 (26%) 
> wall  263417 kB (58%) ggc
> 
> patched.  In the generated code one can see the packing being optimized
> to shifts/ors in registers and the unpacking to shifts/ands.  One
> major optimization inhibitor is the conditional packing of bits,
> this prevents constant propagation of the current bit position.
> 
> Also input/output at a uleb128 rate runs into the surely slow
> byte encoding in lto_{input,output}_uleb128 where we try to
> optimize streaming of leading zeros (does that even pay off?).

The following is the final patch that was bootstrapped and tested
on x86_64-unknown-linux-gnu.  I added a hunk to avoid conditional
bit-packing in packing the tree base flags and the generated code
looks a lot better.

 ipa lto gimple I/O    :   1.86 ( 7%) usr   0.14 (18%) sys   1.96 ( 8%) 
wall       0 kB ( 0%) ggc
 ipa lto decl I/O      :   6.74 (27%) usr   0.12 (15%) sys   6.91 (27%) 
wall  263413 kB (58%) ggc

So I guess at this point we'd need to profile things again.

Ok for trunk?

Thanks,
Richard.

2010-06-12  Richard Guenther  <rguenther@suse.de>

	* lto-streamer.c (cached_bp): Remove.
	(bitpack_delete): Likewise.
	(bitpack_create): Likewise.
	(bp_get_next_word): Likewise.
	(bp_pack_value, bp_unpack_value): Move ...
	* lto-streamer.h (bp_pack_value, bp_unpack_value): ... here.
	Re-implement.
	(struct bitpack_d): Likewise.
	(bitpack_create, lto_output_bitpack, lto_input_bitpack):
	New inline functions.
	* lto-streamer-out.c (lto_output_bitpack): Remove.
	(pack_ts_base_value_fields): Adjust.  Avoid conditional
	bitpacking.
	(pack_value_fields): Adjust.
	(lto_write_tree): Likewise.
	(output_gimple_stmt): Likewise.
	(output_function): Likewise.
	* lto-streamer-in.c (input_gimple_stmt): Adjust.
	(input_function): Likewise.
	(unpack_ts_base_value_fields): Adjust.  Avoid conditional
	bitpacking.
	(lto_input_bitpack): Remove.
	(lto_materialize_tree): Adjust.
	* Makefile.in (ipa-prop.o): Add $(LTO_STREAMER_H) dependency.
	* lto-cgraph.c (lto_output_edge): Adjust.
	(lto_output_node): Likewise.
	(lto_output_varpool_node): Likewise.
	(lto_output_ref): Likewise.
	(input_node): Likewise.
	(input_varpool_node): Likewise.
	(input_ref): Likewise.
	(input_edge): Likewise.
	(output_node_opt_summary): Likewise.
	(input_node_opt_summary): Likewise.
	* ipa-pure-const.c (pure_const_write_summary): Likewise.
	(pure_const_read_summary): Likewise.
	* ipa-prop.c (ipa_write_indirect_edge_info): Likewise.
	(ipa_read_indirect_edge_info): Likewise.
	(ipa_write_node_info): Likewise.
	(ipa_read_node_info): Likewise.

Index: gcc/lto-cgraph.c
===================================================================
*** gcc/lto-cgraph.c.orig	2010-06-12 13:59:51.000000000 +0200
--- gcc/lto-cgraph.c	2010-06-12 16:30:24.000000000 +0200
*************** lto_output_edge (struct lto_simple_outpu
*** 260,266 ****
  {
    unsigned int uid;
    intptr_t ref;
!   struct bitpack_d *bp;
  
    if (edge->indirect_unknown_callee)
      lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_indirect_edge);
--- 260,266 ----
  {
    unsigned int uid;
    intptr_t ref;
!   struct bitpack_d bp;
  
    if (edge->indirect_unknown_callee)
      lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_indirect_edge);
*************** lto_output_edge (struct lto_simple_outpu
*** 280,311 ****
  
    lto_output_sleb128_stream (ob->main_stream, edge->count);
  
!   bp = bitpack_create ();
    uid = flag_wpa ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt);
!   bp_pack_value (bp, uid, HOST_BITS_PER_INT);
!   bp_pack_value (bp, edge->inline_failed, HOST_BITS_PER_INT);
!   bp_pack_value (bp, edge->frequency, HOST_BITS_PER_INT);
!   bp_pack_value (bp, edge->loop_nest, 30);
!   bp_pack_value (bp, edge->indirect_inlining_edge, 1);
!   bp_pack_value (bp, edge->call_stmt_cannot_inline_p, 1);
!   bp_pack_value (bp, edge->can_throw_external, 1);
    if (edge->indirect_unknown_callee)
      {
        int flags = edge->indirect_info->ecf_flags;
!       bp_pack_value (bp, (flags & ECF_CONST) != 0, 1);
!       bp_pack_value (bp, (flags & ECF_PURE) != 0, 1);
!       bp_pack_value (bp, (flags & ECF_NORETURN) != 0, 1);
!       bp_pack_value (bp, (flags & ECF_MALLOC) != 0, 1);
!       bp_pack_value (bp, (flags & ECF_NOTHROW) != 0, 1);
!       bp_pack_value (bp, (flags & ECF_RETURNS_TWICE) != 0, 1);
        /* Flags that should not appear on indirect calls.  */
        gcc_assert (!(flags & (ECF_LOOPING_CONST_OR_PURE
  			     | ECF_MAY_BE_ALLOCA
  			     | ECF_SIBCALL
  			     | ECF_NOVOPS)));
      }
!   lto_output_bitpack (ob->main_stream, bp);
!   bitpack_delete (bp);
  }
  
  /* Return if LIST contain references from other partitions.  */
--- 280,310 ----
  
    lto_output_sleb128_stream (ob->main_stream, edge->count);
  
!   bp = bitpack_create (ob->main_stream);
    uid = flag_wpa ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt);
!   bp_pack_value (&bp, uid, HOST_BITS_PER_INT);
!   bp_pack_value (&bp, edge->inline_failed, HOST_BITS_PER_INT);
!   bp_pack_value (&bp, edge->frequency, HOST_BITS_PER_INT);
!   bp_pack_value (&bp, edge->loop_nest, 30);
!   bp_pack_value (&bp, edge->indirect_inlining_edge, 1);
!   bp_pack_value (&bp, edge->call_stmt_cannot_inline_p, 1);
!   bp_pack_value (&bp, edge->can_throw_external, 1);
    if (edge->indirect_unknown_callee)
      {
        int flags = edge->indirect_info->ecf_flags;
!       bp_pack_value (&bp, (flags & ECF_CONST) != 0, 1);
!       bp_pack_value (&bp, (flags & ECF_PURE) != 0, 1);
!       bp_pack_value (&bp, (flags & ECF_NORETURN) != 0, 1);
!       bp_pack_value (&bp, (flags & ECF_MALLOC) != 0, 1);
!       bp_pack_value (&bp, (flags & ECF_NOTHROW) != 0, 1);
!       bp_pack_value (&bp, (flags & ECF_RETURNS_TWICE) != 0, 1);
        /* Flags that should not appear on indirect calls.  */
        gcc_assert (!(flags & (ECF_LOOPING_CONST_OR_PURE
  			     | ECF_MAY_BE_ALLOCA
  			     | ECF_SIBCALL
  			     | ECF_NOVOPS)));
      }
!   lto_output_bitpack (&bp);
  }
  
  /* Return if LIST contain references from other partitions.  */
*************** lto_output_node (struct lto_simple_outpu
*** 404,410 ****
  		 varpool_node_set vset)
  {
    unsigned int tag;
!   struct bitpack_d *bp;
    bool boundary_p;
    intptr_t ref;
    bool in_other_partition = false;
--- 403,409 ----
  		 varpool_node_set vset)
  {
    unsigned int tag;
!   struct bitpack_d bp;
    bool boundary_p;
    intptr_t ref;
    bool in_other_partition = false;
*************** lto_output_node (struct lto_simple_outpu
*** 458,487 ****
    lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl);
    lto_output_sleb128_stream (ob->main_stream, node->count);
  
-   bp = bitpack_create ();
-   bp_pack_value (bp, node->local.local, 1);
-   bp_pack_value (bp, node->local.externally_visible, 1);
-   bp_pack_value (bp, node->local.finalized, 1);
-   bp_pack_value (bp, node->local.inlinable, 1);
-   bp_pack_value (bp, node->local.versionable, 1);
-   bp_pack_value (bp, node->local.disregard_inline_limits, 1);
-   bp_pack_value (bp, node->local.redefined_extern_inline, 1);
-   bp_pack_value (bp, node->local.vtable_method, 1);
-   bp_pack_value (bp, node->needed, 1);
-   bp_pack_value (bp, node->address_taken, 1);
-   bp_pack_value (bp, node->abstract_and_needed, 1);
-   bp_pack_value (bp, tag == LTO_cgraph_analyzed_node
- 		 && !DECL_EXTERNAL (node->decl)
- 		 && (reachable_from_other_partition_p (node, set)
- 		     || referenced_from_other_partition_p (&node->ref_list, set, vset)), 1);
-   bp_pack_value (bp, node->lowered, 1);
-   bp_pack_value (bp, in_other_partition, 1);
-   bp_pack_value (bp, node->alias, 1);
-   bp_pack_value (bp, node->finalized_by_frontend, 1);
-   bp_pack_value (bp, node->frequency, 2);
-   lto_output_bitpack (ob->main_stream, bp);
-   bitpack_delete (bp);
- 
    if (tag == LTO_cgraph_analyzed_node)
      {
        lto_output_sleb128_stream (ob->main_stream,
--- 457,462 ----
*************** lto_output_node (struct lto_simple_outpu
*** 514,519 ****
--- 489,517 ----
      ref = LCC_NOT_FOUND;
    lto_output_sleb128_stream (ob->main_stream, ref);
  
+   bp = bitpack_create (ob->main_stream);
+   bp_pack_value (&bp, node->local.local, 1);
+   bp_pack_value (&bp, node->local.externally_visible, 1);
+   bp_pack_value (&bp, node->local.finalized, 1);
+   bp_pack_value (&bp, node->local.inlinable, 1);
+   bp_pack_value (&bp, node->local.versionable, 1);
+   bp_pack_value (&bp, node->local.disregard_inline_limits, 1);
+   bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
+   bp_pack_value (&bp, node->local.vtable_method, 1);
+   bp_pack_value (&bp, node->needed, 1);
+   bp_pack_value (&bp, node->address_taken, 1);
+   bp_pack_value (&bp, node->abstract_and_needed, 1);
+   bp_pack_value (&bp, tag == LTO_cgraph_analyzed_node
+ 		 && !DECL_EXTERNAL (node->decl)
+ 		 && (reachable_from_other_partition_p (node, set)
+ 		     || referenced_from_other_partition_p (&node->ref_list, set, vset)), 1);
+   bp_pack_value (&bp, node->lowered, 1);
+   bp_pack_value (&bp, in_other_partition, 1);
+   bp_pack_value (&bp, node->alias, 1);
+   bp_pack_value (&bp, node->finalized_by_frontend, 1);
+   bp_pack_value (&bp, node->frequency, 2);
+   lto_output_bitpack (&bp);
+ 
    if (node->same_body)
      {
        struct cgraph_node *alias;
*************** lto_output_varpool_node (struct lto_simp
*** 561,577 ****
  		         cgraph_node_set set, varpool_node_set vset)
  {
    bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
!   struct bitpack_d *bp;
    struct varpool_node *alias;
    int count = 0;
    int ref;
  
    lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
!   bp = bitpack_create ();
!   bp_pack_value (bp, node->externally_visible, 1);
!   bp_pack_value (bp, node->force_output, 1);
!   bp_pack_value (bp, node->finalized, 1);
!   bp_pack_value (bp, node->alias, 1);
    gcc_assert (!node->alias || !node->extra_name);
    gcc_assert (node->finalized || !node->analyzed);
    gcc_assert (node->needed);
--- 559,575 ----
  		         cgraph_node_set set, varpool_node_set vset)
  {
    bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
!   struct bitpack_d bp;
    struct varpool_node *alias;
    int count = 0;
    int ref;
  
    lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
!   bp = bitpack_create (ob->main_stream);
!   bp_pack_value (&bp, node->externally_visible, 1);
!   bp_pack_value (&bp, node->force_output, 1);
!   bp_pack_value (&bp, node->finalized, 1);
!   bp_pack_value (&bp, node->alias, 1);
    gcc_assert (!node->alias || !node->extra_name);
    gcc_assert (node->finalized || !node->analyzed);
    gcc_assert (node->needed);
*************** lto_output_varpool_node (struct lto_simp
*** 580,601 ****
       labels and share them across LTRANS partitions.  */
    if (DECL_IN_CONSTANT_POOL (node->decl))
      {
!       bp_pack_value (bp, 0, 1);  /* used_from_other_parition.  */
!       bp_pack_value (bp, 0, 1);  /* in_other_partition.  */
      }
    else
      {
!       bp_pack_value (bp, node->analyzed
  		     && referenced_from_other_partition_p (&node->ref_list,
  							   set, vset), 1);
!       bp_pack_value (bp, boundary_p, 1);  /* in_other_partition.  */
      }
    /* Also emit any extra name aliases.  */
    for (alias = node->extra_name; alias; alias = alias->next)
      count++;
!   bp_pack_value (bp, count != 0, 1);
!   lto_output_bitpack (ob->main_stream, bp);
!   bitpack_delete (bp);
    if (node->same_comdat_group && !boundary_p)
      {
        ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group);
--- 578,598 ----
       labels and share them across LTRANS partitions.  */
    if (DECL_IN_CONSTANT_POOL (node->decl))
      {
!       bp_pack_value (&bp, 0, 1);  /* used_from_other_parition.  */
!       bp_pack_value (&bp, 0, 1);  /* in_other_partition.  */
      }
    else
      {
!       bp_pack_value (&bp, node->analyzed
  		     && referenced_from_other_partition_p (&node->ref_list,
  							   set, vset), 1);
!       bp_pack_value (&bp, boundary_p, 1);  /* in_other_partition.  */
      }
    /* Also emit any extra name aliases.  */
    for (alias = node->extra_name; alias; alias = alias->next)
      count++;
!   bp_pack_value (&bp, count != 0, 1);
!   lto_output_bitpack (&bp);
    if (node->same_comdat_group && !boundary_p)
      {
        ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group);
*************** lto_output_ref (struct lto_simple_output
*** 621,631 ****
  		lto_cgraph_encoder_t encoder,
  		lto_varpool_encoder_t varpool_encoder)
  {
!   struct bitpack_d *bp = bitpack_create ();
!   bp_pack_value (bp, ref->refered_type, 1);
!   bp_pack_value (bp, ref->use, 2);
!   lto_output_bitpack (ob->main_stream, bp);
!   bitpack_delete (bp);
    if (ref->refered_type == IPA_REF_CGRAPH)
      {
        int nref = lto_cgraph_encoder_lookup (encoder, ipa_ref_node (ref));
--- 618,628 ----
  		lto_cgraph_encoder_t encoder,
  		lto_varpool_encoder_t varpool_encoder)
  {
!   struct bitpack_d bp;
!   bp = bitpack_create (ob->main_stream);
!   bp_pack_value (&bp, ref->refered_type, 1);
!   bp_pack_value (&bp, ref->use, 2);
!   lto_output_bitpack (&bp);
    if (ref->refered_type == IPA_REF_CGRAPH)
      {
        int nref = lto_cgraph_encoder_lookup (encoder, ipa_ref_node (ref));
*************** input_node (struct lto_file_decl_data *f
*** 981,987 ****
  {
    tree fn_decl;
    struct cgraph_node *node;
!   struct bitpack_d *bp;
    int stack_size = 0;
    unsigned decl_index;
    int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND;
--- 978,984 ----
  {
    tree fn_decl;
    struct cgraph_node *node;
!   struct bitpack_d bp;
    int stack_size = 0;
    unsigned decl_index;
    int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND;
*************** input_node (struct lto_file_decl_data *f
*** 1006,1012 ****
      node = cgraph_node (fn_decl);
  
    node->count = lto_input_sleb128 (ib);
-   bp = lto_input_bitpack (ib);
  
    if (tag == LTO_cgraph_analyzed_node)
      {
--- 1003,1008 ----
*************** input_node (struct lto_file_decl_data *f
*** 1020,1026 ****
      }
  
    ref2 = lto_input_sleb128 (ib);
-   same_body_count = lto_input_uleb128 (ib);
  
    /* Make sure that we have not read this node before.  Nodes that
       have already been read will have their tag stored in the 'aux'
--- 1016,1021 ----
*************** input_node (struct lto_file_decl_data *f
*** 1030,1039 ****
      internal_error ("bytecode stream: found multiple instances of cgraph "
  		    "node %d", node->uid);
  
!   input_overwrite_node (file_data, node, tag, bp, stack_size, self_time,
    			time_inlining_benefit, self_size,
  			size_inlining_benefit);
-   bitpack_delete (bp);
  
    /* Store a reference for now, and fix up later to be a pointer.  */
    node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref;
--- 1025,1034 ----
      internal_error ("bytecode stream: found multiple instances of cgraph "
  		    "node %d", node->uid);
  
!   bp = lto_input_bitpack (ib);
!   input_overwrite_node (file_data, node, tag, &bp, stack_size, self_time,
    			time_inlining_benefit, self_size,
  			size_inlining_benefit);
  
    /* Store a reference for now, and fix up later to be a pointer.  */
    node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref;
*************** input_node (struct lto_file_decl_data *f
*** 1041,1046 ****
--- 1036,1042 ----
    /* Store a reference for now, and fix up later to be a pointer.  */
    node->same_comdat_group = (cgraph_node_ptr) (intptr_t) ref2;
  
+   same_body_count = lto_input_uleb128 (ib);
    while (same_body_count-- > 0)
      {
        tree alias_decl;
*************** input_varpool_node (struct lto_file_decl
*** 1081,1087 ****
    int decl_index;
    tree var_decl;
    struct varpool_node *node;
!   struct bitpack_d *bp;
    bool aliases_p;
    int count;
    int ref = LCC_NOT_FOUND;
--- 1077,1083 ----
    int decl_index;
    tree var_decl;
    struct varpool_node *node;
!   struct bitpack_d bp;
    bool aliases_p;
    int count;
    int ref = LCC_NOT_FOUND;
*************** input_varpool_node (struct lto_file_decl
*** 1092,1108 ****
    node->lto_file_data = file_data;
  
    bp = lto_input_bitpack (ib);
!   node->externally_visible = bp_unpack_value (bp, 1);
!   node->force_output = bp_unpack_value (bp, 1);
!   node->finalized = bp_unpack_value (bp, 1);
!   node->alias = bp_unpack_value (bp, 1);
    node->analyzed = node->finalized; 
!   node->used_from_other_partition = bp_unpack_value (bp, 1);
!   node->in_other_partition = bp_unpack_value (bp, 1);
!   aliases_p = bp_unpack_value (bp, 1);
    if (node->finalized)
      varpool_mark_needed_node (node);
-   bitpack_delete (bp);
    ref = lto_input_sleb128 (ib);
    /* Store a reference for now, and fix up later to be a pointer.  */
    node->same_comdat_group = (struct varpool_node *) (intptr_t) ref;
--- 1088,1103 ----
    node->lto_file_data = file_data;
  
    bp = lto_input_bitpack (ib);
!   node->externally_visible = bp_unpack_value (&bp, 1);
!   node->force_output = bp_unpack_value (&bp, 1);
!   node->finalized = bp_unpack_value (&bp, 1);
!   node->alias = bp_unpack_value (&bp, 1);
    node->analyzed = node->finalized; 
!   node->used_from_other_partition = bp_unpack_value (&bp, 1);
!   node->in_other_partition = bp_unpack_value (&bp, 1);
!   aliases_p = bp_unpack_value (&bp, 1);
    if (node->finalized)
      varpool_mark_needed_node (node);
    ref = lto_input_sleb128 (ib);
    /* Store a reference for now, and fix up later to be a pointer.  */
    node->same_comdat_group = (struct varpool_node *) (intptr_t) ref;
*************** input_ref (struct lto_input_block *ib,
*** 1131,1144 ****
  {
    struct cgraph_node *node = NULL;
    struct varpool_node *varpool_node = NULL;
!   struct bitpack_d *bp;
    enum ipa_ref_type type;
    enum ipa_ref_use use;
  
    bp = lto_input_bitpack (ib);
!   type = (enum ipa_ref_type) bp_unpack_value (bp, 1);
!   use = (enum ipa_ref_use) bp_unpack_value (bp, 2);
!   bitpack_delete (bp);
    if (type == IPA_REF_CGRAPH)
      node = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib));
    else
--- 1126,1138 ----
  {
    struct cgraph_node *node = NULL;
    struct varpool_node *varpool_node = NULL;
!   struct bitpack_d bp;
    enum ipa_ref_type type;
    enum ipa_ref_use use;
  
    bp = lto_input_bitpack (ib);
!   type = (enum ipa_ref_type) bp_unpack_value (&bp, 1);
!   use = (enum ipa_ref_use) bp_unpack_value (&bp, 2);
    if (type == IPA_REF_CGRAPH)
      node = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib));
    else
*************** input_edge (struct lto_input_block *ib,
*** 1163,1169 ****
    int freq;
    unsigned int nest;
    cgraph_inline_failed_t inline_failed;
!   struct bitpack_d *bp;
    enum ld_plugin_symbol_resolution caller_resolution;
    int ecf_flags = 0;
  
--- 1157,1163 ----
    int freq;
    unsigned int nest;
    cgraph_inline_failed_t inline_failed;
!   struct bitpack_d bp;
    enum ld_plugin_symbol_resolution caller_resolution;
    int ecf_flags = 0;
  
*************** input_edge (struct lto_input_block *ib,
*** 1183,1193 ****
    count = (gcov_type) lto_input_sleb128 (ib);
  
    bp = lto_input_bitpack (ib);
!   stmt_id = (unsigned int) bp_unpack_value (bp, HOST_BITS_PER_INT);
!   inline_failed = (cgraph_inline_failed_t) bp_unpack_value (bp,
  							    HOST_BITS_PER_INT);
!   freq = (int) bp_unpack_value (bp, HOST_BITS_PER_INT);
!   nest = (unsigned) bp_unpack_value (bp, 30);
  
    /* If the caller was preempted, don't create the edge.
       ???  Should we ever have edges from a preempted caller?  */
--- 1177,1187 ----
    count = (gcov_type) lto_input_sleb128 (ib);
  
    bp = lto_input_bitpack (ib);
!   stmt_id = (unsigned int) bp_unpack_value (&bp, HOST_BITS_PER_INT);
!   inline_failed = (cgraph_inline_failed_t) bp_unpack_value (&bp,
  							    HOST_BITS_PER_INT);
!   freq = (int) bp_unpack_value (&bp, HOST_BITS_PER_INT);
!   nest = (unsigned) bp_unpack_value (&bp, 30);
  
    /* If the caller was preempted, don't create the edge.
       ???  Should we ever have edges from a preempted caller?  */
*************** input_edge (struct lto_input_block *ib,
*** 1201,1228 ****
    else
      edge = cgraph_create_edge (caller, callee, NULL, count, freq, nest);
  
!   edge->indirect_inlining_edge = bp_unpack_value (bp, 1);
    edge->lto_stmt_uid = stmt_id;
    edge->inline_failed = inline_failed;
!   edge->call_stmt_cannot_inline_p = bp_unpack_value (bp, 1);
!   edge->can_throw_external = bp_unpack_value (bp, 1);
    if (indirect)
      {
!       if (bp_unpack_value (bp, 1))
  	ecf_flags |= ECF_CONST;
!       if (bp_unpack_value (bp, 1))
  	ecf_flags |= ECF_PURE;
!       if (bp_unpack_value (bp, 1))
  	ecf_flags |= ECF_NORETURN;
!       if (bp_unpack_value (bp, 1))
  	ecf_flags |= ECF_MALLOC;
!       if (bp_unpack_value (bp, 1))
  	ecf_flags |= ECF_NOTHROW;
!       if (bp_unpack_value (bp, 1))
  	ecf_flags |= ECF_RETURNS_TWICE;
        edge->indirect_info->ecf_flags = ecf_flags;
      }
-   bitpack_delete (bp);
  }
  
  
--- 1195,1221 ----
    else
      edge = cgraph_create_edge (caller, callee, NULL, count, freq, nest);
  
!   edge->indirect_inlining_edge = bp_unpack_value (&bp, 1);
    edge->lto_stmt_uid = stmt_id;
    edge->inline_failed = inline_failed;
!   edge->call_stmt_cannot_inline_p = bp_unpack_value (&bp, 1);
!   edge->can_throw_external = bp_unpack_value (&bp, 1);
    if (indirect)
      {
!       if (bp_unpack_value (&bp, 1))
  	ecf_flags |= ECF_CONST;
!       if (bp_unpack_value (&bp, 1))
  	ecf_flags |= ECF_PURE;
!       if (bp_unpack_value (&bp, 1))
  	ecf_flags |= ECF_NORETURN;
!       if (bp_unpack_value (&bp, 1))
  	ecf_flags |= ECF_MALLOC;
!       if (bp_unpack_value (&bp, 1))
  	ecf_flags |= ECF_NOTHROW;
!       if (bp_unpack_value (&bp, 1))
  	ecf_flags |= ECF_RETURNS_TWICE;
        edge->indirect_info->ecf_flags = ecf_flags;
      }
  }
  
  
*************** output_node_opt_summary (struct output_b
*** 1470,1476 ****
    unsigned int index;
    bitmap_iterator bi;
    struct ipa_replace_map *map;
!   struct bitpack_d *bp;
    int i;
  
    lto_output_uleb128_stream (ob->main_stream,
--- 1463,1469 ----
    unsigned int index;
    bitmap_iterator bi;
    struct ipa_replace_map *map;
!   struct bitpack_d bp;
    int i;
  
    lto_output_uleb128_stream (ob->main_stream,
*************** output_node_opt_summary (struct output_b
*** 1497,1507 ****
        gcc_assert (parm);
        lto_output_uleb128_stream (ob->main_stream, parm_num);
        lto_output_tree (ob, map->new_tree, true);
!       bp = bitpack_create ();
!       bp_pack_value (bp, map->replace_p, 1);
!       bp_pack_value (bp, map->ref_p, 1);
!       lto_output_bitpack (ob->main_stream, bp);
!       bitpack_delete (bp);
      }
  }
  
--- 1490,1499 ----
        gcc_assert (parm);
        lto_output_uleb128_stream (ob->main_stream, parm_num);
        lto_output_tree (ob, map->new_tree, true);
!       bp = bitpack_create (ob->main_stream);
!       bp_pack_value (&bp, map->replace_p, 1);
!       bp_pack_value (&bp, map->ref_p, 1);
!       lto_output_bitpack (&bp);
      }
  }
  
*************** input_node_opt_summary (struct cgraph_no
*** 1547,1553 ****
    int i;
    int count;
    int bit;
!   struct bitpack_d *bp;
  
    count = lto_input_uleb128 (ib_main);
    if (count)
--- 1539,1545 ----
    int i;
    int count;
    int bit;
!   struct bitpack_d bp;
  
    count = lto_input_uleb128 (ib_main);
    if (count)
*************** input_node_opt_summary (struct cgraph_no
*** 1580,1588 ****
        map->old_tree = NULL;
        map->new_tree = lto_input_tree (ib_main, data_in);
        bp = lto_input_bitpack (ib_main);
!       map->replace_p = bp_unpack_value (bp, 1);
!       map->ref_p = bp_unpack_value (bp, 1);
!       bitpack_delete (bp);
      }
  }
  
--- 1572,1579 ----
        map->old_tree = NULL;
        map->new_tree = lto_input_tree (ib_main, data_in);
        bp = lto_input_bitpack (ib_main);
!       map->replace_p = bp_unpack_value (&bp, 1);
!       map->ref_p = bp_unpack_value (&bp, 1);
      }
  }
  
Index: gcc/ipa-pure-const.c
===================================================================
*** gcc/ipa-pure-const.c.orig	2010-06-12 13:59:51.000000000 +0200
--- gcc/ipa-pure-const.c	2010-06-12 16:06:36.000000000 +0200
*************** pure_const_write_summary (cgraph_node_se
*** 943,949 ****
        node = csi_node (csi);
        if (node->analyzed && has_function_state (node))
  	{
! 	  struct bitpack_d *bp;
  	  funct_state fs;
  	  int node_ref;
  	  lto_cgraph_encoder_t encoder;
--- 943,949 ----
        node = csi_node (csi);
        if (node->analyzed && has_function_state (node))
  	{
! 	  struct bitpack_d bp;
  	  funct_state fs;
  	  int node_ref;
  	  lto_cgraph_encoder_t encoder;
*************** pure_const_write_summary (cgraph_node_se
*** 956,969 ****
  
  	  /* Note that flags will need to be read in the opposite
  	     order as we are pushing the bitflags into FLAGS.  */
! 	  bp = bitpack_create ();
! 	  bp_pack_value (bp, fs->pure_const_state, 2);
! 	  bp_pack_value (bp, fs->state_previously_known, 2);
! 	  bp_pack_value (bp, fs->looping_previously_known, 1);
! 	  bp_pack_value (bp, fs->looping, 1);
! 	  bp_pack_value (bp, fs->can_throw, 1);
! 	  lto_output_bitpack (ob->main_stream, bp);
! 	  bitpack_delete (bp);
  	}
      }
  
--- 956,968 ----
  
  	  /* Note that flags will need to be read in the opposite
  	     order as we are pushing the bitflags into FLAGS.  */
! 	  bp = bitpack_create (ob->main_stream);
! 	  bp_pack_value (&bp, fs->pure_const_state, 2);
! 	  bp_pack_value (&bp, fs->state_previously_known, 2);
! 	  bp_pack_value (&bp, fs->looping_previously_known, 1);
! 	  bp_pack_value (&bp, fs->looping, 1);
! 	  bp_pack_value (&bp, fs->can_throw, 1);
! 	  lto_output_bitpack (&bp);
  	}
      }
  
*************** pure_const_read_summary (void)
*** 998,1004 ****
  	    {
  	      unsigned int index;
  	      struct cgraph_node *node;
! 	      struct bitpack_d *bp;
  	      funct_state fs;
  	      lto_cgraph_encoder_t encoder;
  
--- 997,1003 ----
  	    {
  	      unsigned int index;
  	      struct cgraph_node *node;
! 	      struct bitpack_d bp;
  	      funct_state fs;
  	      lto_cgraph_encoder_t encoder;
  
*************** pure_const_read_summary (void)
*** 1013,1024 ****
  		 pushed into FLAGS).  */
  	      bp = lto_input_bitpack (ib);
  	      fs->pure_const_state
! 			= (enum pure_const_state_e) bp_unpack_value (bp, 2);
  	      fs->state_previously_known
! 			= (enum pure_const_state_e) bp_unpack_value (bp, 2);
! 	      fs->looping_previously_known = bp_unpack_value (bp, 1);
! 	      fs->looping = bp_unpack_value (bp, 1);
! 	      fs->can_throw = bp_unpack_value (bp, 1);
  	      if (dump_file)
  		{
  		  int flags = flags_from_decl_or_type (node->decl);
--- 1012,1023 ----
  		 pushed into FLAGS).  */
  	      bp = lto_input_bitpack (ib);
  	      fs->pure_const_state
! 			= (enum pure_const_state_e) bp_unpack_value (&bp, 2);
  	      fs->state_previously_known
! 			= (enum pure_const_state_e) bp_unpack_value (&bp, 2);
! 	      fs->looping_previously_known = bp_unpack_value (&bp, 1);
! 	      fs->looping = bp_unpack_value (&bp, 1);
! 	      fs->can_throw = bp_unpack_value (&bp, 1);
  	      if (dump_file)
  		{
  		  int flags = flags_from_decl_or_type (node->decl);
*************** pure_const_read_summary (void)
*** 1042,1048 ****
  		  if (fs->can_throw)
  		    fprintf (dump_file,"  function is locally throwing\n");
  		}
- 	      bitpack_delete (bp);
  	    }
  
  	  lto_destroy_simple_input_block (file_data,
--- 1041,1046 ----
Index: gcc/lto-streamer-out.c
===================================================================
*** gcc/lto-streamer-out.c.orig	2010-06-12 13:59:51.000000000 +0200
--- gcc/lto-streamer-out.c	2010-06-12 16:34:16.000000000 +0200
*************** destroy_output_block (struct output_bloc
*** 151,170 ****
  }
  
  
- /* Output bitpack BP to output stream S.  */
- 
- void
- lto_output_bitpack (struct lto_output_stream *s, struct bitpack_d *bp)
- {
-   unsigned i;
-   bitpack_word_t v;
- 
-   lto_output_uleb128_stream (s, VEC_length (bitpack_word_t, bp->values));
-   for (i = 0; VEC_iterate (bitpack_word_t, bp->values, i, v); i++)
-     lto_output_uleb128_stream (s, v);
- }
- 
- 
  /* Output STRING of LEN characters to the string
     table in OB. The string might or might not include a trailing '\0'.
     Then put the index onto the INDEX_STREAM.  */
--- 151,156 ----
*************** pack_ts_base_value_fields (struct bitpac
*** 335,346 ****
--- 321,336 ----
  	 so we skip it here.  */
        bp_pack_value (bp, TREE_PUBLIC (expr), 1);
      }
+   else
+     bp_pack_value (bp, 0, 4);
    bp_pack_value (bp, TREE_ADDRESSABLE (expr), 1);
    bp_pack_value (bp, TREE_THIS_VOLATILE (expr), 1);
    if (DECL_P (expr))
      bp_pack_value (bp, DECL_UNSIGNED (expr), 1);
    else if (TYPE_P (expr))
      bp_pack_value (bp, TYPE_UNSIGNED (expr), 1);
+   else
+     bp_pack_value (bp, 0, 1);
    /* We write debug info two times, do not confuse the second one.  */
    bp_pack_value (bp, TYPE_P (expr) ? 0 : TREE_ASM_WRITTEN (expr), 1);
    bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
*************** pack_ts_base_value_fields (struct bitpac
*** 352,359 ****
    bp_pack_value (bp, TREE_DEPRECATED (expr), 1);
    if (TYPE_P (expr))
      bp_pack_value (bp, TYPE_SATURATING (expr), 1);
!   if (TREE_CODE (expr) == SSA_NAME)
      bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
  }
  
  
--- 342,351 ----
    bp_pack_value (bp, TREE_DEPRECATED (expr), 1);
    if (TYPE_P (expr))
      bp_pack_value (bp, TYPE_SATURATING (expr), 1);
!   else if (TREE_CODE (expr) == SSA_NAME)
      bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
+   else
+     bp_pack_value (bp, 0, 1);
  }
  
  
*************** pack_ts_block_value_fields (struct bitpa
*** 544,557 ****
  
  /* Pack all the non-pointer fields in EXPR into a bit pack.  */
  
! static struct bitpack_d *
! pack_value_fields (tree expr)
  {
    enum tree_code code;
-   struct bitpack_d *bp;
  
    code = TREE_CODE (expr);
-   bp = bitpack_create ();
  
    /* Note that all these functions are highly sensitive to changes in
       the types and sizes of each of the fields being packed.  */
--- 536,547 ----
  
  /* Pack all the non-pointer fields in EXPR into a bit pack.  */
  
! static void
! pack_value_fields (struct bitpack_d *bp, tree expr)
  {
    enum tree_code code;
  
    code = TREE_CODE (expr);
  
    /* Note that all these functions are highly sensitive to changes in
       the types and sizes of each of the fields being packed.  */
*************** pack_value_fields (tree expr)
*** 598,605 ****
        /* This is only used by High GIMPLE.  */
        gcc_unreachable ();
      }
- 
-   return bp;
  }
  
  
--- 588,593 ----
*************** lto_output_builtin_tree (struct output_b
*** 1293,1299 ****
  static void
  lto_write_tree (struct output_block *ob, tree expr, bool ref_p, int ix)
  {
!   struct bitpack_d *bp;
  
    /* Write the header, containing everything needed to materialize
       EXPR on the reading side.  */
--- 1281,1287 ----
  static void
  lto_write_tree (struct output_block *ob, tree expr, bool ref_p, int ix)
  {
!   struct bitpack_d bp;
  
    /* Write the header, containing everything needed to materialize
       EXPR on the reading side.  */
*************** lto_write_tree (struct output_block *ob,
*** 1301,1309 ****
  
    /* Pack all the non-pointer fields in EXPR into a bitpack and write
       the resulting bitpack.  */
!   bp = pack_value_fields (expr);
!   lto_output_bitpack (ob->main_stream, bp);
!   bitpack_delete (bp);
  
    /* Write all the pointer fields in EXPR.  */
    lto_output_tree_pointers (ob, expr, ref_p);
--- 1289,1297 ----
  
    /* Pack all the non-pointer fields in EXPR into a bitpack and write
       the resulting bitpack.  */
!   bp = bitpack_create (ob->main_stream);
!   pack_value_fields (&bp, expr);
!   lto_output_bitpack (&bp);
  
    /* Write all the pointer fields in EXPR.  */
    lto_output_tree_pointers (ob, expr, ref_p);
*************** output_gimple_stmt (struct output_block
*** 1660,1666 ****
    unsigned i;
    enum gimple_code code;
    enum LTO_tags tag;
!   struct bitpack_d *bp;
  
    /* Emit identifying tag.  */
    code = gimple_code (stmt);
--- 1648,1654 ----
    unsigned i;
    enum gimple_code code;
    enum LTO_tags tag;
!   struct bitpack_d bp;
  
    /* Emit identifying tag.  */
    code = gimple_code (stmt);
*************** output_gimple_stmt (struct output_block
*** 1668,1682 ****
    output_record_start (ob, tag);
  
    /* Emit the tuple header.  */
!   bp = bitpack_create ();
!   bp_pack_value (bp, gimple_num_ops (stmt), sizeof (unsigned) * 8);
!   bp_pack_value (bp, gimple_no_warning_p (stmt), 1);
    if (is_gimple_assign (stmt))
!     bp_pack_value (bp, gimple_assign_nontemporal_move_p (stmt), 1);
!   bp_pack_value (bp, gimple_has_volatile_ops (stmt), 1);
!   bp_pack_value (bp, stmt->gsbase.subcode, 16);
!   lto_output_bitpack (ob->main_stream, bp);
!   bitpack_delete (bp);
  
    /* Emit location information for the statement.  */
    lto_output_location (ob, gimple_location (stmt));
--- 1656,1669 ----
    output_record_start (ob, tag);
  
    /* Emit the tuple header.  */
!   bp = bitpack_create (ob->main_stream);
!   bp_pack_value (&bp, gimple_num_ops (stmt), sizeof (unsigned) * 8);
!   bp_pack_value (&bp, gimple_no_warning_p (stmt), 1);
    if (is_gimple_assign (stmt))
!     bp_pack_value (&bp, gimple_assign_nontemporal_move_p (stmt), 1);
!   bp_pack_value (&bp, gimple_has_volatile_ops (stmt), 1);
!   bp_pack_value (&bp, stmt->gsbase.subcode, 16);
!   lto_output_bitpack (&bp);
  
    /* Emit location information for the statement.  */
    lto_output_location (ob, gimple_location (stmt));
*************** produce_asm (struct output_block *ob, tr
*** 1847,1853 ****
  static void
  output_function (struct cgraph_node *node)
  {
!   struct bitpack_d *bp;
    tree function;
    struct function *fn;
    basic_block bb;
--- 1834,1840 ----
  static void
  output_function (struct cgraph_node *node)
  {
!   struct bitpack_d bp;
    tree function;
    struct function *fn;
    basic_block bb;
*************** output_function (struct cgraph_node *nod
*** 1872,1895 ****
    output_record_start (ob, LTO_function);
  
    /* Write all the attributes for FN.  */
!   bp = bitpack_create ();
!   bp_pack_value (bp, fn->is_thunk, 1);
!   bp_pack_value (bp, fn->has_local_explicit_reg_vars, 1);
!   bp_pack_value (bp, fn->after_tree_profile, 1);
!   bp_pack_value (bp, fn->returns_pcc_struct, 1);
!   bp_pack_value (bp, fn->returns_struct, 1);
!   bp_pack_value (bp, fn->can_throw_non_call_exceptions, 1);
!   bp_pack_value (bp, fn->always_inline_functions_inlined, 1);
!   bp_pack_value (bp, fn->after_inlining, 1);
!   bp_pack_value (bp, fn->dont_save_pending_sizes_p, 1);
!   bp_pack_value (bp, fn->stdarg, 1);
!   bp_pack_value (bp, fn->has_nonlocal_label, 1);
!   bp_pack_value (bp, fn->calls_alloca, 1);
!   bp_pack_value (bp, fn->calls_setjmp, 1);
!   bp_pack_value (bp, fn->va_list_fpr_size, 8);
!   bp_pack_value (bp, fn->va_list_gpr_size, 8);
!   lto_output_bitpack (ob->main_stream, bp);
!   bitpack_delete (bp);
  
    /* Output current IL state of the function.  */
    output_uleb128 (ob, fn->curr_properties);
--- 1859,1881 ----
    output_record_start (ob, LTO_function);
  
    /* Write all the attributes for FN.  */
!   bp = bitpack_create (ob->main_stream);
!   bp_pack_value (&bp, fn->is_thunk, 1);
!   bp_pack_value (&bp, fn->has_local_explicit_reg_vars, 1);
!   bp_pack_value (&bp, fn->after_tree_profile, 1);
!   bp_pack_value (&bp, fn->returns_pcc_struct, 1);
!   bp_pack_value (&bp, fn->returns_struct, 1);
!   bp_pack_value (&bp, fn->can_throw_non_call_exceptions, 1);
!   bp_pack_value (&bp, fn->always_inline_functions_inlined, 1);
!   bp_pack_value (&bp, fn->after_inlining, 1);
!   bp_pack_value (&bp, fn->dont_save_pending_sizes_p, 1);
!   bp_pack_value (&bp, fn->stdarg, 1);
!   bp_pack_value (&bp, fn->has_nonlocal_label, 1);
!   bp_pack_value (&bp, fn->calls_alloca, 1);
!   bp_pack_value (&bp, fn->calls_setjmp, 1);
!   bp_pack_value (&bp, fn->va_list_fpr_size, 8);
!   bp_pack_value (&bp, fn->va_list_gpr_size, 8);
!   lto_output_bitpack (&bp);
  
    /* Output current IL state of the function.  */
    output_uleb128 (ob, fn->curr_properties);
Index: gcc/lto-streamer-in.c
===================================================================
*** gcc/lto-streamer-in.c.orig	2010-06-12 13:59:51.000000000 +0200
--- gcc/lto-streamer-in.c	2010-06-12 16:34:08.000000000 +0200
*************** input_gimple_stmt (struct lto_input_bloc
*** 1001,1020 ****
    enum gimple_code code;
    unsigned HOST_WIDE_INT num_ops;
    size_t i;
!   struct bitpack_d *bp;
  
    code = lto_tag_to_gimple_code (tag);
  
    /* Read the tuple header.  */
    bp = lto_input_bitpack (ib);
!   num_ops = bp_unpack_value (bp, sizeof (unsigned) * 8);
    stmt = gimple_alloc (code, num_ops);
!   stmt->gsbase.no_warning = bp_unpack_value (bp, 1);
    if (is_gimple_assign (stmt))
!     stmt->gsbase.nontemporal_move = bp_unpack_value (bp, 1);
!   stmt->gsbase.has_volatile_ops = bp_unpack_value (bp, 1);
!   stmt->gsbase.subcode = bp_unpack_value (bp, 16);
!   bitpack_delete (bp);
  
    /* Read location information.  */
    gimple_set_location (stmt, lto_input_location (ib, data_in));
--- 1001,1019 ----
    enum gimple_code code;
    unsigned HOST_WIDE_INT num_ops;
    size_t i;
!   struct bitpack_d bp;
  
    code = lto_tag_to_gimple_code (tag);
  
    /* Read the tuple header.  */
    bp = lto_input_bitpack (ib);
!   num_ops = bp_unpack_value (&bp, sizeof (unsigned) * 8);
    stmt = gimple_alloc (code, num_ops);
!   stmt->gsbase.no_warning = bp_unpack_value (&bp, 1);
    if (is_gimple_assign (stmt))
!     stmt->gsbase.nontemporal_move = bp_unpack_value (&bp, 1);
!   stmt->gsbase.has_volatile_ops = bp_unpack_value (&bp, 1);
!   stmt->gsbase.subcode = bp_unpack_value (&bp, 16);
  
    /* Read location information.  */
    gimple_set_location (stmt, lto_input_location (ib, data_in));
*************** input_function (tree fn_decl, struct dat
*** 1291,1297 ****
    enum LTO_tags tag;
    gimple *stmts;
    basic_block bb;
!   struct bitpack_d *bp;
    struct cgraph_node *node;
    tree args, narg, oarg;
  
--- 1290,1296 ----
    enum LTO_tags tag;
    gimple *stmts;
    basic_block bb;
!   struct bitpack_d bp;
    struct cgraph_node *node;
    tree args, narg, oarg;
  
*************** input_function (tree fn_decl, struct dat
*** 1304,1325 ****
  
    /* Read all the attributes for FN.  */
    bp = lto_input_bitpack (ib);
!   fn->is_thunk = bp_unpack_value (bp, 1);
!   fn->has_local_explicit_reg_vars = bp_unpack_value (bp, 1);
!   fn->after_tree_profile = bp_unpack_value (bp, 1);
!   fn->returns_pcc_struct = bp_unpack_value (bp, 1);
!   fn->returns_struct = bp_unpack_value (bp, 1);
!   fn->can_throw_non_call_exceptions = bp_unpack_value (bp, 1);
!   fn->always_inline_functions_inlined = bp_unpack_value (bp, 1);
!   fn->after_inlining = bp_unpack_value (bp, 1);
!   fn->dont_save_pending_sizes_p = bp_unpack_value (bp, 1);
!   fn->stdarg = bp_unpack_value (bp, 1);
!   fn->has_nonlocal_label = bp_unpack_value (bp, 1);
!   fn->calls_alloca = bp_unpack_value (bp, 1);
!   fn->calls_setjmp = bp_unpack_value (bp, 1);
!   fn->va_list_fpr_size = bp_unpack_value (bp, 8);
!   fn->va_list_gpr_size = bp_unpack_value (bp, 8);
!   bitpack_delete (bp);
  
    /* Input the current IL state of the function.  */
    fn->curr_properties = lto_input_uleb128 (ib);
--- 1303,1323 ----
  
    /* Read all the attributes for FN.  */
    bp = lto_input_bitpack (ib);
!   fn->is_thunk = bp_unpack_value (&bp, 1);
!   fn->has_local_explicit_reg_vars = bp_unpack_value (&bp, 1);
!   fn->after_tree_profile = bp_unpack_value (&bp, 1);
!   fn->returns_pcc_struct = bp_unpack_value (&bp, 1);
!   fn->returns_struct = bp_unpack_value (&bp, 1);
!   fn->can_throw_non_call_exceptions = bp_unpack_value (&bp, 1);
!   fn->always_inline_functions_inlined = bp_unpack_value (&bp, 1);
!   fn->after_inlining = bp_unpack_value (&bp, 1);
!   fn->dont_save_pending_sizes_p = bp_unpack_value (&bp, 1);
!   fn->stdarg = bp_unpack_value (&bp, 1);
!   fn->has_nonlocal_label = bp_unpack_value (&bp, 1);
!   fn->calls_alloca = bp_unpack_value (&bp, 1);
!   fn->calls_setjmp = bp_unpack_value (&bp, 1);
!   fn->va_list_fpr_size = bp_unpack_value (&bp, 8);
!   fn->va_list_gpr_size = bp_unpack_value (&bp, 8);
  
    /* Input the current IL state of the function.  */
    fn->curr_properties = lto_input_uleb128 (ib);
*************** unpack_ts_base_value_fields (struct bitp
*** 1581,1592 ****
--- 1579,1594 ----
  	 so we skip it here.  */
        TREE_PUBLIC (expr) = (unsigned) bp_unpack_value (bp, 1);
      }
+   else
+     bp_unpack_value (bp, 4);
    TREE_ADDRESSABLE (expr) = (unsigned) bp_unpack_value (bp, 1);
    TREE_THIS_VOLATILE (expr) = (unsigned) bp_unpack_value (bp, 1);
    if (DECL_P (expr))
      DECL_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
    else if (TYPE_P (expr))
      TYPE_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
+   else
+     bp_unpack_value (bp, 1);
    TREE_ASM_WRITTEN (expr) = (unsigned) bp_unpack_value (bp, 1);
    TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1);
    TREE_USED (expr) = (unsigned) bp_unpack_value (bp, 1);
*************** unpack_ts_base_value_fields (struct bitp
*** 1597,1604 ****
    TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1);
    if (TYPE_P (expr))
      TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
!   if (TREE_CODE (expr) == SSA_NAME)
      SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1);
  }
  
  
--- 1599,1608 ----
    TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1);
    if (TYPE_P (expr))
      TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
!   else if (TREE_CODE (expr) == SSA_NAME)
      SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1);
+   else
+     bp_unpack_value (bp, 1);
  }
  
  
*************** unpack_value_fields (struct bitpack_d *b
*** 1858,1889 ****
  }
  
  
- /* Read a bitpack from input block IB.  */
- 
- struct bitpack_d *
- lto_input_bitpack (struct lto_input_block *ib)
- {
-   unsigned i, num_words;
-   struct bitpack_d *bp;
- 
-   bp = bitpack_create ();
- 
-   /* If we are about to read more than a handful of words, something
-      is wrong.  This check is overly strict, but it acts as an early
-      warning.  No streamed object has hundreds of bits in its fields.  */
-   num_words = lto_input_uleb128 (ib);
-   gcc_assert (num_words < 20);
- 
-   for (i = 0; i < num_words; i++)
-     {
-       bitpack_word_t w = lto_input_uleb128 (ib);
-       VEC_safe_push (bitpack_word_t, heap, bp->values, w);
-     }
- 
-   return bp;
- }
- 
- 
  /* Materialize a new tree from input block IB using descriptors in
     DATA_IN.  The code for the new tree should match TAG.  Store in
     *IX_P the index into the reader cache where the new tree is stored.  */
--- 1862,1867 ----
*************** static tree
*** 1892,1898 ****
  lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
  		      enum LTO_tags tag, int *ix_p)
  {
!   struct bitpack_d *bp;
    enum tree_code code;
    tree result;
  #ifdef LTO_STREAMER_DEBUG
--- 1870,1876 ----
  lto_materialize_tree (struct lto_input_block *ib, struct data_in *data_in,
  		      enum LTO_tags tag, int *ix_p)
  {
!   struct bitpack_d bp;
    enum tree_code code;
    tree result;
  #ifdef LTO_STREAMER_DEBUG
*************** lto_materialize_tree (struct lto_input_b
*** 1957,1968 ****
  
    /* The first word in BP contains the code of the tree that we
       are about to read.  */
!   code = (enum tree_code) bp_unpack_value (bp, 16);
    lto_tag_check (lto_tree_code_to_tag (code), tag);
  
    /* Unpack all the value fields from BP.  */
!   unpack_value_fields (bp, result);
!   bitpack_delete (bp);
  
    /* Enter RESULT in the reader cache.  This will make RESULT
       available so that circular references in the rest of the tree
--- 1935,1945 ----
  
    /* The first word in BP contains the code of the tree that we
       are about to read.  */
!   code = (enum tree_code) bp_unpack_value (&bp, 16);
    lto_tag_check (lto_tree_code_to_tag (code), tag);
  
    /* Unpack all the value fields from BP.  */
!   unpack_value_fields (&bp, result);
  
    /* Enter RESULT in the reader cache.  This will make RESULT
       available so that circular references in the rest of the tree
Index: gcc/ipa-prop.c
===================================================================
*** gcc/ipa-prop.c.orig	2010-06-12 13:59:51.000000000 +0200
--- gcc/ipa-prop.c	2010-06-12 16:11:26.000000000 +0200
*************** ipa_write_indirect_edge_info (struct out
*** 2403,2416 ****
  			      struct cgraph_edge *cs)
  {
    struct cgraph_indirect_call_info *ii = cs->indirect_info;
!   struct bitpack_d *bp;
  
    lto_output_sleb128_stream (ob->main_stream, ii->param_index);
    lto_output_sleb128_stream (ob->main_stream, ii->anc_offset);
!   bp = bitpack_create ();
!   bp_pack_value (bp, ii->polymorphic, 1);
!   lto_output_bitpack (ob->main_stream, bp);
!   bitpack_delete (bp);
  
    if (ii->polymorphic)
      {
--- 2403,2415 ----
  			      struct cgraph_edge *cs)
  {
    struct cgraph_indirect_call_info *ii = cs->indirect_info;
!   struct bitpack_d bp;
  
    lto_output_sleb128_stream (ob->main_stream, ii->param_index);
    lto_output_sleb128_stream (ob->main_stream, ii->anc_offset);
!   bp = bitpack_create (ob->main_stream);
!   bp_pack_value (&bp, ii->polymorphic, 1);
!   lto_output_bitpack (&bp);
  
    if (ii->polymorphic)
      {
*************** ipa_read_indirect_edge_info (struct lto_
*** 2428,2440 ****
  			     struct cgraph_edge *cs)
  {
    struct cgraph_indirect_call_info *ii = cs->indirect_info;
!   struct bitpack_d *bp;
  
    ii->param_index = (int) lto_input_sleb128 (ib);
    ii->anc_offset = (HOST_WIDE_INT) lto_input_sleb128 (ib);
    bp = lto_input_bitpack (ib);
!   ii->polymorphic = bp_unpack_value (bp, 1);
!   bitpack_delete (bp);
    if (ii->polymorphic)
      {
        ii->otr_token = (HOST_WIDE_INT) lto_input_sleb128 (ib);
--- 2427,2438 ----
  			     struct cgraph_edge *cs)
  {
    struct cgraph_indirect_call_info *ii = cs->indirect_info;
!   struct bitpack_d bp;
  
    ii->param_index = (int) lto_input_sleb128 (ib);
    ii->anc_offset = (HOST_WIDE_INT) lto_input_sleb128 (ib);
    bp = lto_input_bitpack (ib);
!   ii->polymorphic = bp_unpack_value (&bp, 1);
    if (ii->polymorphic)
      {
        ii->otr_token = (HOST_WIDE_INT) lto_input_sleb128 (ib);
*************** ipa_write_node_info (struct output_block
*** 2452,2477 ****
    struct ipa_node_params *info = IPA_NODE_REF (node);
    int j;
    struct cgraph_edge *e;
!   struct bitpack_d *bp;
  
    encoder = ob->decl_state->cgraph_node_encoder;
    node_ref = lto_cgraph_encoder_encode (encoder, node);
    lto_output_uleb128_stream (ob->main_stream, node_ref);
  
!   bp = bitpack_create ();
!   bp_pack_value (bp, info->called_with_var_arguments, 1);
!   bp_pack_value (bp, info->uses_analysis_done, 1);
    gcc_assert (info->modification_analysis_done
  	      || ipa_get_param_count (info) == 0);
    gcc_assert (!info->node_enqueued);
    gcc_assert (!info->ipcp_orig_node);
    for (j = 0; j < ipa_get_param_count (info); j++)
      {
!       bp_pack_value (bp, info->params[j].modified, 1);
!       bp_pack_value (bp, info->params[j].used, 1);
      }
!   lto_output_bitpack (ob->main_stream, bp);
!   bitpack_delete (bp);
    for (e = node->callees; e; e = e->next_callee)
      {
        struct ipa_edge_args *args = IPA_EDGE_REF (e);
--- 2450,2474 ----
    struct ipa_node_params *info = IPA_NODE_REF (node);
    int j;
    struct cgraph_edge *e;
!   struct bitpack_d bp;
  
    encoder = ob->decl_state->cgraph_node_encoder;
    node_ref = lto_cgraph_encoder_encode (encoder, node);
    lto_output_uleb128_stream (ob->main_stream, node_ref);
  
!   bp = bitpack_create (ob->main_stream);
!   bp_pack_value (&bp, info->called_with_var_arguments, 1);
!   bp_pack_value (&bp, info->uses_analysis_done, 1);
    gcc_assert (info->modification_analysis_done
  	      || ipa_get_param_count (info) == 0);
    gcc_assert (!info->node_enqueued);
    gcc_assert (!info->ipcp_orig_node);
    for (j = 0; j < ipa_get_param_count (info); j++)
      {
!       bp_pack_value (&bp, info->params[j].modified, 1);
!       bp_pack_value (&bp, info->params[j].used, 1);
      }
!   lto_output_bitpack (&bp);
    for (e = node->callees; e; e = e->next_callee)
      {
        struct ipa_edge_args *args = IPA_EDGE_REF (e);
*************** ipa_read_node_info (struct lto_input_blo
*** 2494,2506 ****
    struct ipa_node_params *info = IPA_NODE_REF (node);
    int k;
    struct cgraph_edge *e;
!   struct bitpack_d *bp;
  
    ipa_initialize_node_params (node);
  
    bp = lto_input_bitpack (ib);
!   info->called_with_var_arguments = bp_unpack_value (bp, 1);
!   info->uses_analysis_done = bp_unpack_value (bp, 1);
    if (ipa_get_param_count (info) != 0)
      {
        info->modification_analysis_done = true;
--- 2491,2503 ----
    struct ipa_node_params *info = IPA_NODE_REF (node);
    int k;
    struct cgraph_edge *e;
!   struct bitpack_d bp;
  
    ipa_initialize_node_params (node);
  
    bp = lto_input_bitpack (ib);
!   info->called_with_var_arguments = bp_unpack_value (&bp, 1);
!   info->uses_analysis_done = bp_unpack_value (&bp, 1);
    if (ipa_get_param_count (info) != 0)
      {
        info->modification_analysis_done = true;
*************** ipa_read_node_info (struct lto_input_blo
*** 2509,2518 ****
    info->node_enqueued = false;
    for (k = 0; k < ipa_get_param_count (info); k++)
      {
!       info->params[k].modified = bp_unpack_value (bp, 1);
!       info->params[k].used = bp_unpack_value (bp, 1);
      }
-   bitpack_delete (bp);
    for (e = node->callees; e; e = e->next_callee)
      {
        struct ipa_edge_args *args = IPA_EDGE_REF (e);
--- 2506,2514 ----
    info->node_enqueued = false;
    for (k = 0; k < ipa_get_param_count (info); k++)
      {
!       info->params[k].modified = bp_unpack_value (&bp, 1);
!       info->params[k].used = bp_unpack_value (&bp, 1);
      }
    for (e = node->callees; e; e = e->next_callee)
      {
        struct ipa_edge_args *args = IPA_EDGE_REF (e);
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in.orig	2010-06-12 13:59:51.000000000 +0200
--- gcc/Makefile.in	2010-06-12 14:01:15.000000000 +0200
*************** ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SY
*** 2995,3001 ****
     langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(DIAGNOSTIC_H) \
     $(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) \
     $(TREE_INLINE_H) $(GIMPLE_H) $(GIMPLE_FOLD_H) $(TIMEVAR_H) \
!    tree-pretty-print.h gimple-pretty-print.h
  ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H)  $(TREE_H) $(TARGET_H) \
     $(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) $(GGC_H) 
--- 2995,3001 ----
     langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(DIAGNOSTIC_H) \
     $(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) \
     $(TREE_INLINE_H) $(GIMPLE_H) $(GIMPLE_FOLD_H) $(TIMEVAR_H) \
!    tree-pretty-print.h gimple-pretty-print.h $(LTO_STREAMER_H)
  ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H)  $(TREE_H) $(TARGET_H) \
     $(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) $(GGC_H) 
Index: gcc/lto-streamer.c
===================================================================
*** gcc/lto-streamer.c.orig	2010-06-12 13:59:51.000000000 +0200
--- gcc/lto-streamer.c	2010-06-12 14:01:15.000000000 +0200
*************** print_lto_report (void)
*** 266,412 ****
  	     lto_section_name[i], lto_stats.section_size[i]);
  }
  
- /* We cache a single bitpack assuming that usually at most one is
-    life.  This saves repeated re-allocations.  */
- static struct bitpack_d *cached_bp;
- 
- /* Create a new bitpack.  */
- 
- struct bitpack_d *
- bitpack_create (void)
- {
-   if (cached_bp)
-     {
-       struct bitpack_d *bp = cached_bp;
-       cached_bp = NULL;
-       return bp;
-     }
-   return XCNEW (struct bitpack_d);
- }
- 
- 
- /* Free the memory used by bitpack BP.  */
- 
- void
- bitpack_delete (struct bitpack_d *bp)
- {
-   if (!cached_bp)
-     {
-       bp->num_bits = 0;
-       bp->first_unused_bit = 0;
-       VEC_truncate (bitpack_word_t, bp->values, 0);
-       cached_bp = bp;
-       return;
-     }
-   VEC_free (bitpack_word_t, heap, bp->values);
-   free (bp);
- }
- 
- 
- /* Return an index to the word in bitpack BP that contains the
-    next NBITS.  */
- 
- static inline unsigned
- bp_get_next_word (struct bitpack_d *bp, unsigned nbits)
- {
-   unsigned last, ix;
- 
-   /* In principle, the next word to use is determined by the
-      number of bits already processed in BP.  */
-   ix = bp->num_bits / BITS_PER_BITPACK_WORD;
- 
-   /* All the encoded bit patterns in BP are contiguous, therefore if
-      the next NBITS would straddle over two different words, move the
-      index to the next word and update the number of encoded bits
-      by adding up the hole of unused bits created by this move.  */
-   bp->first_unused_bit %= BITS_PER_BITPACK_WORD;
-   last = bp->first_unused_bit + nbits - 1;
-   if (last >= BITS_PER_BITPACK_WORD)
-     {
-       ix++;
-       bp->num_bits += (BITS_PER_BITPACK_WORD - bp->first_unused_bit);
-       bp->first_unused_bit = 0;
-     }
- 
-   return ix;
- }
- 
- 
- /* Pack NBITS of value VAL into bitpack BP.  */
- 
- void
- bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits)
- {
-   unsigned ix;
-   bitpack_word_t word;
- 
-   /* We cannot encode more bits than BITS_PER_BITPACK_WORD.  */
- #ifdef ENABLE_CHECKING
-   gcc_assert (nbits > 0 && nbits <= BITS_PER_BITPACK_WORD);
- #endif
- 
-   /* Compute which word will contain the next NBITS.  */
-   ix = bp_get_next_word (bp, nbits);
-   if (ix >= VEC_length (bitpack_word_t, bp->values))
-     {
-       /* If there is no room left in the last word of the values
- 	 array, add a new word.  Additionally, we should only
- 	 need to add a single word, since every pack operation cannot
- 	 use more bits than fit in a single word.  */
-       VEC_safe_push (bitpack_word_t, heap, bp->values, 0);
-     }
- 
-   /* Grab the last word to pack VAL into.  */
-   word = VEC_index (bitpack_word_t, bp->values, ix);
- 
-   /* To fit VAL in WORD, we need to shift VAL to the left to
-      skip the bottom BP->FIRST_UNUSED_BIT bits.  */
-   val <<= bp->first_unused_bit;
- 
-   /* Update WORD with VAL.  */
-   word |= val;
- 
-   /* Update BP.  */
-   VEC_replace (bitpack_word_t, bp->values, ix, word);
-   bp->num_bits += nbits;
-   bp->first_unused_bit += nbits;
- }
- 
- 
- /* Unpack the next NBITS from bitpack BP.  */
- 
- bitpack_word_t
- bp_unpack_value (struct bitpack_d *bp, unsigned nbits)
- {
-   bitpack_word_t val, word, mask;
-   unsigned ix;
- 
-   /* We cannot decode more bits than BITS_PER_BITPACK_WORD.  */
-   gcc_assert (nbits > 0 && nbits <= BITS_PER_BITPACK_WORD);
- 
-   /* Compute which word contains the next NBITS.  */
-   ix = bp_get_next_word (bp, nbits);
-   word = VEC_index (bitpack_word_t, bp->values, ix);
- 
-   /* Compute the mask to get NBITS from WORD.  */
-   mask = (nbits == BITS_PER_BITPACK_WORD)
- 	 ? (bitpack_word_t) -1
- 	 : ((bitpack_word_t) 1 << nbits) - 1;
- 
-   /* Shift WORD to the right to skip over the bits already decoded
-      in word.  */
-   word >>= bp->first_unused_bit;
- 
-   /* Apply the mask to obtain the requested value.  */
-   val = word & mask;
- 
-   /* Update BP->NUM_BITS for the next unpack operation.  */
-   bp->num_bits += nbits;
-   bp->first_unused_bit += nbits;
- 
-   return val;
- }
- 
  
  /* Check that all the TS_* structures handled by the lto_output_* and
     lto_input_* routines are exactly ALL the structures defined in
--- 266,271 ----
Index: gcc/lto-streamer.h
===================================================================
*** gcc/lto-streamer.h.orig	2010-06-12 13:59:51.000000000 +0200
--- gcc/lto-streamer.h	2010-06-12 16:28:09.000000000 +0200
*************** DEF_VEC_ALLOC_I(bitpack_word_t, heap);
*** 156,172 ****
  
  struct bitpack_d
  {
!   /* Total number of bits packed/unpacked so far.  */
!   size_t num_bits;
  
!   /* Values are stored contiguously, so there may be internal
!      fragmentation (words with unused bits).  Therefore, we need to
!      keep track of the first available bit in the last word of the
!      bitpack.  */
!   size_t first_unused_bit;
  
!   /* Vector of words holding the packed values.  */
!   VEC(bitpack_word_t, heap) *values;
  };
  
  /* Tags representing the various IL objects written to the bytecode file
--- 156,169 ----
  
  struct bitpack_d
  {
!   /* The position of the first unused or unconsumed bit in the word.  */
!   unsigned pos;
  
!   /* The current word we are (un)packing.  */
!   bitpack_word_t word;
  
!   /* The lto_output_stream or the lto_input_block we are streaming to/from.  */
!   void *stream;
  };
  
  /* Tags representing the various IL objects written to the bytecode file
*************** extern bitmap lto_bitmap_alloc (void);
*** 820,829 ****
  extern void lto_bitmap_free (bitmap);
  extern char *lto_get_section_name (int, const char *);
  extern void print_lto_report (void);
- extern struct bitpack_d *bitpack_create (void);
- extern void bitpack_delete (struct bitpack_d *);
- extern void bp_pack_value (struct bitpack_d *, bitpack_word_t, unsigned);
- extern bitpack_word_t bp_unpack_value (struct bitpack_d *, unsigned);
  extern bool lto_streamer_cache_insert (struct lto_streamer_cache_d *, tree,
  				       int *, unsigned *);
  extern bool lto_streamer_cache_insert_at (struct lto_streamer_cache_d *, tree,
--- 817,822 ----
*************** extern void lto_input_function_body (str
*** 851,857 ****
  				     const char *);
  extern void lto_input_constructors_and_inits (struct lto_file_decl_data *,
  					      const char *);
- extern struct bitpack_d *lto_input_bitpack (struct lto_input_block *);
  extern void lto_init_reader (void);
  extern struct data_in *lto_data_in_create (struct lto_file_decl_data *,
  				    const char *, unsigned,
--- 844,849 ----
*************** extern void lto_register_decl_definition
*** 864,870 ****
  extern struct output_block *create_output_block (enum lto_section_type);
  extern void destroy_output_block (struct output_block *);
  extern void lto_output_tree (struct output_block *, tree, bool);
- extern void lto_output_bitpack (struct lto_output_stream *, struct bitpack_d *);
  extern void produce_asm (struct output_block *ob, tree fn);
  
  
--- 856,861 ----
*************** DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, typ
*** 1077,1080 ****
--- 1068,1152 ----
  DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
  DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
  
+ /* Returns a new bit-packing context for bit-packing into S.  */
+ static inline struct bitpack_d
+ bitpack_create (struct lto_output_stream *s)
+ {
+   struct bitpack_d bp;
+   bp.pos = 0;
+   bp.word = 0;
+   bp.stream = (void *)s;
+   return bp;
+ }
+ 
+ /* Pack the NBITS bit sized value VAL into the bit-packing context BP.  */
+ static inline void
+ bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits)
+ {
+   bitpack_word_t word = bp->word;
+   int pos = bp->pos;
+   /* If val does not fit into the current bitpack word switch to the
+      next one.  */
+   if (pos + nbits > BITS_PER_BITPACK_WORD)
+     {
+       lto_output_uleb128_stream ((struct lto_output_stream *) bp->stream, word);
+       word = val;
+       pos = nbits;
+     }
+   else
+     {
+       word |= val << pos;
+       pos += nbits;
+     }
+   bp->word = word;
+   bp->pos = pos;
+ }
+ 
+ /* Finishes bit-packing of BP.  */
+ static inline void
+ lto_output_bitpack (struct bitpack_d *bp)
+ {
+   lto_output_uleb128_stream ((struct lto_output_stream *) bp->stream,
+ 			     bp->word);
+   bp->word = 0;
+   bp->pos = 0;
+ }
+ 
+ /* Returns a new bit-packing context for bit-unpacking from IB.  */
+ static inline struct bitpack_d
+ lto_input_bitpack (struct lto_input_block *ib)
+ {
+   struct bitpack_d bp;
+   bp.word = lto_input_uleb128 (ib);
+   bp.pos = 0;
+   bp.stream = (void *)ib;
+   return bp;
+ }
+ 
+ /* Unpacks NBITS bits from the bit-packing context BP and returns them.  */
+ static inline bitpack_word_t
+ bp_unpack_value (struct bitpack_d *bp, unsigned nbits)
+ {
+   bitpack_word_t mask, val;
+   int pos = bp->pos;
+ 
+   mask = (nbits == BITS_PER_BITPACK_WORD
+ 	  ? (bitpack_word_t) -1
+ 	  : ((bitpack_word_t) 1 << nbits) - 1);
+ 
+   /* If there are not continuous nbits in the current bitpack word
+      switch to the next one.  */
+   if (pos + nbits > BITS_PER_BITPACK_WORD)
+     {
+       bp->word = val = lto_input_uleb128 ((struct lto_input_block *)bp->stream);
+       bp->pos = nbits;
+       return val & mask;
+     }
+   val = bp->word;
+   val >>= pos;
+   bp->pos = pos + nbits;
+ 
+   return val & mask;
+ }
+ 
  #endif /* GCC_LTO_STREAMER_H  */



More information about the Gcc-patches mailing list