On Fri, May 27, 2011 at 10:54 AM, Jan Hubicka <hubi...@ucw.cz> wrote: > Hi, > here is updated patch incorporating the feedback. I now use variant of uleb > format, > just do 4 bit chunks instead of 8bit. It works better in my tests and is also > used > by LLVM so it must be cool ;) > > I also fixed off by one error in filename streaming. While debugging this I > noticed that bitpack will have random effect when the value passed does not > fit > in range (i.e. the bits will end up in next packed values). Adding assert on > this > I found one place where we try to pack negative value in it. Fixed by using > my > new functions, but wonder what the logic of code is, given that we always > pack 0 or -1 as alias set.
Yeah, I think diego noticed this as well. Micha has a point in that everything should be a single bitpack which suitable points of re-alignment (to also make optimizing the packing possible). But that's more work and can be done on top of this. > Bootstrapped/regtested x86_64-linux, OK? Ok. Thanks, Richard. > * lto-streamer-out.c (lto_string_index): break out from...; offset by 1 > so 0 means NULL string. > (lto_output_string_with_length): ... here. > (lto_output_string, output_string_cst, output_identifier): Update > handling > of NULL strings. > (lto_output_location_bitpack): New function. > (lto_output_location): Use it. > (lto_output_tree_ref): Use output_record_start. > (pack_ts_type_common_value_fields): Pack aliagn & alias set in var len > values. > * lto-streamer-in.c (string_for_index): Break out from ...; offset > values by 1. > (input_string_internal): ... here; > (input_string_cst, input_identifier, lto_input_string): Update > handling of NULL strings. > (lto_input_location_bitpack): New function > (lto_input_location): Use it. > (unpack_ts_type_common_value_fields): Pack align & alias in var len > values. > * lto-streamer.h (bp_pack_val_len_unsigned, bp_pack_val_len_int, > bp_unpack_val_len_unsigned, bp_unpack_val_len_int): Declare. > (bp_pack_value): Sanity check the value range. > * lto-section-in.c (bp_unpack_val_len_unsigned, bp_unpack_val_len_int): > New functions. > * lto-section-out.h (bp_pack_val_len_unsigned, bp_pack_val_len_int): > New functions. > Index: lto-streamer-out.c > =================================================================== > *** lto-streamer-out.c (revision 174268) > --- lto-streamer-out.c (working copy) > *************** destroy_output_block (struct output_bloc > *** 143,158 **** > free (ob); > } > > ! > ! /* 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. */ > > ! void > ! lto_output_string_with_length (struct output_block *ob, > ! struct lto_output_stream *index_stream, > ! const char *s, > ! unsigned int len) > { > struct string_slot **slot; > struct string_slot s_slot; > --- 143,156 ---- > free (ob); > } > > ! /* Return index used to reference STRING of LEN characters in the string > table > ! in OB. The string might or might not include a trailing '\0'. > Then put the index onto the INDEX_STREAM. */ > > ! static unsigned > ! lto_string_index (struct output_block *ob, > ! const char *s, > ! unsigned int len) > { > struct string_slot **slot; > struct string_slot s_slot; > *************** lto_output_string_with_length (struct ou > *** 164,172 **** > s_slot.len = len; > s_slot.slot_num = 0; > > - /* Indicate that this is not a NULL string. */ > - lto_output_uleb128_stream (index_stream, 0); > - > slot = (struct string_slot **) htab_find_slot (ob->string_hash_table, > &s_slot, INSERT); > if (*slot == NULL) > --- 162,167 ---- > *************** lto_output_string_with_length (struct ou > *** 180,197 **** > new_slot->len = len; > new_slot->slot_num = start; > *slot = new_slot; > - lto_output_uleb128_stream (index_stream, start); > lto_output_uleb128_stream (string_stream, len); > lto_output_data_stream (string_stream, string, len); > } > else > { > struct string_slot *old_slot = *slot; > - lto_output_uleb128_stream (index_stream, old_slot->slot_num); > free (string); > } > } > > /* Output the '\0' terminated STRING to the string > table in OB. Then put the index onto the INDEX_STREAM. */ > > --- 175,207 ---- > new_slot->len = len; > new_slot->slot_num = start; > *slot = new_slot; > lto_output_uleb128_stream (string_stream, len); > lto_output_data_stream (string_stream, string, len); > + return start + 1; > } > else > { > struct string_slot *old_slot = *slot; > free (string); > + return old_slot->slot_num + 1; > } > } > > + > + /* 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. */ > + > + void > + lto_output_string_with_length (struct output_block *ob, > + struct lto_output_stream *index_stream, > + const char *s, > + unsigned int len) > + { > + lto_output_uleb128_stream (index_stream, > + lto_string_index (ob, s, len)); > + } > + > /* Output the '\0' terminated STRING to the string > table in OB. Then put the index onto the INDEX_STREAM. */ > > *************** lto_output_string (struct output_block * > *** 204,210 **** > lto_output_string_with_length (ob, index_stream, string, > strlen (string) + 1); > else > ! lto_output_uleb128_stream (index_stream, 1); > } > > > --- 214,220 ---- > lto_output_string_with_length (ob, index_stream, string, > strlen (string) + 1); > else > ! lto_output_1_stream (index_stream, 0); > } > > > *************** output_string_cst (struct output_block * > *** 221,227 **** > TREE_STRING_POINTER (string), > TREE_STRING_LENGTH (string )); > else > ! lto_output_uleb128_stream (index_stream, 1); > } > > > --- 231,237 ---- > TREE_STRING_POINTER (string), > TREE_STRING_LENGTH (string )); > else > ! lto_output_1_stream (index_stream, 0); > } > > > *************** output_identifier (struct output_block * > *** 238,246 **** > IDENTIFIER_POINTER (id), > IDENTIFIER_LENGTH (id)); > else > ! lto_output_uleb128_stream (index_stream, 1); > } > > /* Write a zero to the output stream. */ > > static void > --- 248,257 ---- > IDENTIFIER_POINTER (id), > IDENTIFIER_LENGTH (id)); > else > ! lto_output_1_stream (index_stream, 0); > } > > + > /* Write a zero to the output stream. */ > > static void > *************** pack_ts_type_common_value_fields (struct > *** 504,511 **** > bp_pack_value (bp, TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr), 2); > bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1); > bp_pack_value (bp, TYPE_READONLY (expr), 1); > ! bp_pack_value (bp, TYPE_ALIGN (expr), HOST_BITS_PER_INT); > ! bp_pack_value (bp, TYPE_ALIAS_SET (expr) == 0 ? 0 : -1, > HOST_BITS_PER_INT); > } > > > --- 515,522 ---- > bp_pack_value (bp, TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr), 2); > bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1); > bp_pack_value (bp, TYPE_READONLY (expr), 1); > ! bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr)); > ! bp_pack_var_len_int (bp, TYPE_ALIAS_SET (expr) == 0 ? 0 : -1); > } > > > *************** pack_value_fields (struct bitpack_d *bp, > *** 587,618 **** > } > > > ! /* Emit location LOC to output block OB. */ > > ! static void > ! lto_output_location (struct output_block *ob, location_t loc) > { > expanded_location xloc; > > if (loc == UNKNOWN_LOCATION) > ! { > ! lto_output_string (ob, ob->main_stream, NULL); > ! return; > ! } > > xloc = expand_location (loc); > > ! lto_output_string (ob, ob->main_stream, xloc.file); > ! output_sleb128 (ob, xloc.line); > ! output_sleb128 (ob, xloc.column); > ! output_sleb128 (ob, xloc.sysp); > ! > ob->current_file = xloc.file; > ob->current_line = xloc.line; > ob->current_col = xloc.column; > } > > > /* Return true if tree node T is written to various tables. For these > nodes, we sometimes want to write their phyiscal representation > (via lto_output_tree), and sometimes we need to emit an index > --- 598,652 ---- > } > > > ! /* Output info about new location into bitpack BP. > ! After outputting bitpack, lto_output_location_data has > ! to be done to output actual data. */ > > ! static inline void > ! lto_output_location_bitpack (struct bitpack_d *bp, > ! struct output_block *ob, > ! location_t loc) > { > expanded_location xloc; > > + bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1); > if (loc == UNKNOWN_LOCATION) > ! return; > > xloc = expand_location (loc); > > ! bp_pack_value (bp, ob->current_file != xloc.file, 1); > ! if (ob->current_file != xloc.file) > ! bp_pack_var_len_unsigned (bp, lto_string_index (ob, > ! xloc.file, > ! strlen (xloc.file) + 1)); > ob->current_file = xloc.file; > + > + bp_pack_value (bp, ob->current_line != xloc.line, 1); > + if (ob->current_line != xloc.line) > + bp_pack_var_len_unsigned (bp, xloc.line); > ob->current_line = xloc.line; > + > + bp_pack_value (bp, ob->current_col != xloc.column, 1); > + if (ob->current_col != xloc.column) > + bp_pack_var_len_unsigned (bp, xloc.column); > ob->current_col = xloc.column; > } > > > + /* Emit location LOC to output block OB. > + When bitpack is handy, it is more space effecient to call > + lto_output_location_bitpack with existing bitpack. */ > + > + static void > + lto_output_location (struct output_block *ob, location_t loc) > + { > + struct bitpack_d bp = bitpack_create (ob->main_stream); > + lto_output_location_bitpack (&bp, ob, loc); > + lto_output_bitpack (&bp); > + } > + > + > /* Return true if tree node T is written to various tables. For these > nodes, we sometimes want to write their phyiscal representation > (via lto_output_tree), and sometimes we need to emit an index > *************** lto_output_tree_ref (struct output_block > *** 642,648 **** > > if (expr == NULL_TREE) > { > ! output_zero (ob); > return; > } > > --- 676,682 ---- > > if (expr == NULL_TREE) > { > ! output_record_start (ob, LTO_null); > return; > } > > Index: lto-streamer-in.c > =================================================================== > *** lto-streamer-in.c (revision 174268) > --- lto-streamer-in.c (working copy) > *************** eq_string_slot_node (const void *p1, con > *** 132,150 **** > IB. Write the length to RLEN. */ > > static const char * > ! input_string_internal (struct data_in *data_in, struct lto_input_block *ib, > ! unsigned int *rlen) > { > struct lto_input_block str_tab; > unsigned int len; > - unsigned int loc; > const char *result; > > ! /* Read the location of the string from IB. */ > ! loc = lto_input_uleb128 (ib); > > /* Get the string stored at location LOC in DATA_IN->STRINGS. */ > ! LTO_INIT_INPUT_BLOCK (str_tab, data_in->strings, loc, > data_in->strings_len); > len = lto_input_uleb128 (&str_tab); > *rlen = len; > > --- 132,153 ---- > IB. Write the length to RLEN. */ > > static const char * > ! string_for_index (struct data_in *data_in, > ! unsigned int loc, > ! unsigned int *rlen) > { > struct lto_input_block str_tab; > unsigned int len; > const char *result; > > ! if (!loc) > ! { > ! *rlen = 0; > ! return NULL; > ! } > > /* Get the string stored at location LOC in DATA_IN->STRINGS. */ > ! LTO_INIT_INPUT_BLOCK (str_tab, data_in->strings, loc - 1, > data_in->strings_len); > len = lto_input_uleb128 (&str_tab); > *rlen = len; > > *************** input_string_internal (struct data_in *d > *** 157,162 **** > --- 160,176 ---- > } > > > + /* Read a string from the string table in DATA_IN using input block > + IB. Write the length to RLEN. */ > + > + static const char * > + input_string_internal (struct data_in *data_in, struct lto_input_block *ib, > + unsigned int *rlen) > + { > + return string_for_index (data_in, lto_input_uleb128 (ib), rlen); > + } > + > + > /* Read a STRING_CST from the string table in DATA_IN using input > block IB. */ > > *************** input_string_cst (struct data_in *data_i > *** 165,177 **** > { > unsigned int len; > const char * ptr; > - unsigned int is_null; > - > - is_null = lto_input_uleb128 (ib); > - if (is_null) > - return NULL; > > ptr = input_string_internal (data_in, ib, &len); > return build_string (len, ptr); > } > > --- 179,188 ---- > { > unsigned int len; > const char * ptr; > > ptr = input_string_internal (data_in, ib, &len); > + if (!ptr) > + return NULL; > return build_string (len, ptr); > } > > *************** input_identifier (struct data_in *data_i > *** 184,196 **** > { > unsigned int len; > const char *ptr; > - unsigned int is_null; > - > - is_null = lto_input_uleb128 (ib); > - if (is_null) > - return NULL; > > ptr = input_string_internal (data_in, ib, &len); > return get_identifier_with_length (ptr, len); > } > > --- 195,204 ---- > { > unsigned int len; > const char *ptr; > > ptr = input_string_internal (data_in, ib, &len); > + if (!ptr) > + return NULL; > return get_identifier_with_length (ptr, len); > } > > *************** lto_input_string (struct data_in *data_i > *** 215,227 **** > { > unsigned int len; > const char *ptr; > - unsigned int is_null; > - > - is_null = lto_input_uleb128 (ib); > - if (is_null) > - return NULL; > > ptr = input_string_internal (data_in, ib, &len); > if (ptr[len - 1] != '\0') > internal_error ("bytecode stream: found non-null terminated string"); > > --- 223,232 ---- > { > unsigned int len; > const char *ptr; > > ptr = input_string_internal (data_in, ib, &len); > + if (!ptr) > + return NULL; > if (ptr[len - 1] != '\0') > internal_error ("bytecode stream: found non-null terminated string"); > > *************** clear_line_info (struct data_in *data_in > *** 284,320 **** > } > > > ! /* Read a location from input block IB. */ > > static location_t > ! lto_input_location (struct lto_input_block *ib, struct data_in *data_in) > { > ! expanded_location xloc; > > ! xloc.file = lto_input_string (data_in, ib); > ! if (xloc.file == NULL) > return UNKNOWN_LOCATION; > > ! xloc.file = canon_file_name (xloc.file); > ! xloc.line = lto_input_sleb128 (ib); > ! xloc.column = lto_input_sleb128 (ib); > ! xloc.sysp = lto_input_sleb128 (ib); > > ! if (data_in->current_file != xloc.file) > { > ! if (data_in->current_file) > linemap_add (line_table, LC_LEAVE, false, NULL, 0); > > ! linemap_add (line_table, LC_ENTER, xloc.sysp, xloc.file, xloc.line); > } > ! else if (data_in->current_line != xloc.line) > ! linemap_line_start (line_table, xloc.line, xloc.column); > > - data_in->current_file = xloc.file; > - data_in->current_line = xloc.line; > - data_in->current_col = xloc.column; > > ! return linemap_position_for_column (line_table, xloc.column); > } > > > --- 289,345 ---- > } > > > ! /* Read a location bitpack from input block IB. */ > > static location_t > ! lto_input_location_bitpack (struct data_in *data_in, struct bitpack_d *bp) > { > ! bool file_change, line_change, column_change; > ! unsigned len; > ! bool prev_file = data_in->current_file != NULL; > > ! if (bp_unpack_value (bp, 1)) > return UNKNOWN_LOCATION; > > ! file_change = bp_unpack_value (bp, 1); > ! if (file_change) > ! data_in->current_file = canon_file_name > ! (string_for_index (data_in, > ! bp_unpack_var_len_unsigned > (bp), > ! &len)); > ! > ! line_change = bp_unpack_value (bp, 1); > ! if (line_change) > ! data_in->current_line = bp_unpack_var_len_unsigned (bp); > ! > ! column_change = bp_unpack_value (bp, 1); > ! if (column_change) > ! data_in->current_col = bp_unpack_var_len_unsigned (bp); > > ! if (file_change) > { > ! if (prev_file) > linemap_add (line_table, LC_LEAVE, false, NULL, 0); > > ! linemap_add (line_table, LC_ENTER, false, data_in->current_file, > ! data_in->current_line); > } > ! else if (line_change) > ! linemap_line_start (line_table, data_in->current_line, > data_in->current_col); > ! > ! return linemap_position_for_column (line_table, data_in->current_col); > ! } > > > ! /* Read a location from input block IB. */ > ! > ! static location_t > ! lto_input_location (struct lto_input_block *ib, struct data_in *data_in) > ! { > ! struct bitpack_d bp; > ! > ! bp = lto_input_bitpack (ib); > ! return lto_input_location_bitpack (data_in, &bp); > } > > > *************** unpack_ts_type_common_value_fields (stru > *** 1766,1773 **** > = (unsigned) bp_unpack_value (bp, 2); > TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1); > TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1); > ! TYPE_ALIGN (expr) = (unsigned) bp_unpack_value (bp, HOST_BITS_PER_INT); > ! TYPE_ALIAS_SET (expr) = bp_unpack_value (bp, HOST_BITS_PER_INT); > } > > > --- 1791,1798 ---- > = (unsigned) bp_unpack_value (bp, 2); > TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1); > TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1); > ! TYPE_ALIGN (expr) = bp_unpack_var_len_unsigned (bp); > ! TYPE_ALIAS_SET (expr) = bp_unpack_var_len_int (bp); > } > > > Index: lto-section-in.c > =================================================================== > *** lto-section-in.c (revision 174268) > --- lto-section-in.c (working copy) > *************** lto_input_sleb128 (struct lto_input_bloc > *** 127,132 **** > --- 127,177 ---- > } > > > + /* Unpack VAL from BP in a variant of uleb format. */ > + > + unsigned HOST_WIDE_INT > + bp_unpack_var_len_unsigned (struct bitpack_d *bp) > + { > + unsigned HOST_WIDE_INT result = 0; > + int shift = 0; > + unsigned HOST_WIDE_INT half_byte; > + > + while (true) > + { > + half_byte = bp_unpack_value (bp, 4); > + result |= (half_byte & 0x7) << shift; > + shift += 3; > + if ((half_byte & 0x8) == 0) > + return result; > + } > + } > + > + > + /* Unpack VAL from BP in a variant of sleb format. */ > + > + HOST_WIDE_INT > + bp_unpack_var_len_int (struct bitpack_d *bp) > + { > + HOST_WIDE_INT result = 0; > + int shift = 0; > + unsigned HOST_WIDE_INT half_byte; > + > + while (true) > + { > + half_byte = bp_unpack_value (bp, 4); > + result |= (half_byte & 0x7) << shift; > + shift += 3; > + if ((half_byte & 0x8) == 0) > + { > + if ((shift < HOST_BITS_PER_WIDE_INT) && (half_byte & 0x4)) > + result |= - ((HOST_WIDE_INT)1 << shift); > + > + return result; > + } > + } > + } > + > + > /* Hooks so that the ipa passes can call into the lto front end to get > sections. */ > > Index: lto-section-out.c > =================================================================== > *** lto-section-out.c (revision 174268) > --- lto-section-out.c (working copy) > *************** lto_output_sleb128_stream (struct lto_ou > *** 330,335 **** > --- 330,377 ---- > } > > > + /* Pack WORK into BP in a variant of uleb format. */ > + > + void > + bp_pack_var_len_unsigned (struct bitpack_d *bp, unsigned HOST_WIDE_INT work) > + { > + do > + { > + unsigned int half_byte = (work & 0x7); > + work >>= 3; > + if (work != 0) > + /* More half_bytes to follow. */ > + half_byte |= 0x8; > + > + bp_pack_value (bp, half_byte, 4); > + } > + while (work != 0); > + } > + > + > + /* Pack WORK into BP in a variant of sleb format. */ > + > + void > + bp_pack_var_len_int (struct bitpack_d *bp, HOST_WIDE_INT work) > + { > + int more, half_byte; > + > + do > + { > + half_byte = (work & 0x7); > + /* arithmetic shift */ > + work >>= 3; > + more = !((work == 0 && (half_byte & 0x4) == 0) > + || (work == -1 && (half_byte & 0x4) != 0)); > + if (more) > + half_byte |= 0x8; > + > + bp_pack_value (bp, half_byte, 4); > + } > + while (more); > + } > + > + > /* Lookup NAME in ENCODER. If NAME is not found, create a new entry in > ENCODER for NAME with the next available index of ENCODER, then > print the index to OBS. True is returned if NAME was added to > Index: lto-streamer.h > =================================================================== > *** lto-streamer.h (revision 174268) > --- lto-streamer.h (working copy) > *************** extern void lto_section_overrun (struct > *** 774,779 **** > --- 774,783 ---- > extern void lto_value_range_error (const char *, > HOST_WIDE_INT, HOST_WIDE_INT, > HOST_WIDE_INT) ATTRIBUTE_NORETURN; > + extern void bp_pack_var_len_unsigned (struct bitpack_d *, unsigned > HOST_WIDE_INT); > + extern void bp_pack_var_len_int (struct bitpack_d *, HOST_WIDE_INT); > + extern unsigned HOST_WIDE_INT bp_unpack_var_len_unsigned (struct bitpack_d > *); > + extern HOST_WIDE_INT bp_unpack_var_len_int (struct bitpack_d *); > > /* In lto-section-out.c */ > extern hashval_t lto_hash_decl_slot_node (const void *); > *************** bp_pack_value (struct bitpack_d *bp, bit > *** 1110,1115 **** > --- 1114,1124 ---- > { > bitpack_word_t word = bp->word; > int pos = bp->pos; > + > + /* Verify that VAL fits in the NBITS. */ > + gcc_checking_assert (nbits == BITS_PER_BITPACK_WORD > + || !(val & ~(((bitpack_word_t)1<<nbits)-1))); > + > /* If val does not fit into the current bitpack word switch to the > next one. */ > if (pos + nbits > BITS_PER_BITPACK_WORD) >