2005-06-08 Eric Botcazou PR debug/21946 * dwarf2out.c (add_loc_descr_op_piece): Move to the DWARF2_DEBUGGING_INFO section. 2005-06-07 Jakub Jelinek PR debug/21946 * dwarf2out.c (add_loc_descr_op_piece): New function. (multiple_reg_loc_descriptor, concat_loc_descriptor, loc_descriptor): Use it. * var-tracking.c: Include regs.h and expr.h. (emit_note_insn_var_location): Skip over pieces where offset is smaller than previous offset plus previous piece mode size. Optimize adjacent hard registers or memory locations. * Makefile.in (var-tracking.o): Depend on $(REGS_H) and $(EXPR_H). --- gcc/dwarf2out.c.jj 2005-06-07 00:39:11.000000000 +0200 +++ gcc/dwarf2out.c 2005-06-07 00:54:10.000000000 +0200 @@ -3747,6 +3748,7 @@ static dw_die_ref subrange_type_die (tre static dw_die_ref modified_type_die (tree, int, int, dw_die_ref); static int type_is_enum (tree); static unsigned int dbx_reg_number (rtx); +static void add_loc_descr_op_piece (dw_loc_descr_ref *, int); static dw_loc_descr_ref reg_loc_descriptor (rtx); static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int); static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx); @@ -8176,6 +8178,26 @@ dbx_reg_number (rtx rtl) return DBX_REGISTER_NUMBER (regno); } +/* Optionally add a DW_OP_piece term to a location description expression. + DW_OP_piece is only added if the location description expression already + doesn't end with DW_OP_piece. */ + +static void +add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size) +{ + dw_loc_descr_ref loc; + + if (*list_head != NULL) + { + /* Find the end of the chain. */ + for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next) + ; + + if (loc->dw_loc_opc != DW_OP_piece) + loc->dw_loc_next = new_loc_descr (DW_OP_piece, size, 0); + } +} + /* Return a location descriptor that designates a machine register or zero if there is none. */ @@ -8235,7 +8257,7 @@ multiple_reg_loc_descriptor (rtx rtl, rt t = one_reg_loc_descriptor (reg); add_loc_descr (&loc_result, t); - add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0)); + add_loc_descr_op_piece (&loc_result, size); ++reg; } return loc_result; @@ -8256,7 +8278,7 @@ multiple_reg_loc_descriptor (rtx rtl, rt t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i))); add_loc_descr (&loc_result, t); size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0))); - add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0)); + add_loc_descr_op_piece (&loc_result, size); } return loc_result; } @@ -8551,14 +8573,10 @@ concat_loc_descriptor (rtx x0, rtx x1) return 0; cc_loc_result = x0_ref; - add_loc_descr (&cc_loc_result, - new_loc_descr (DW_OP_piece, - GET_MODE_SIZE (GET_MODE (x0)), 0)); + add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x0))); add_loc_descr (&cc_loc_result, x1_ref); - add_loc_descr (&cc_loc_result, - new_loc_descr (DW_OP_piece, - GET_MODE_SIZE (GET_MODE (x1)), 0)); + add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1))); return cc_loc_result; } @@ -8619,8 +8637,7 @@ loc_descriptor (rtx rtl, bool can_use_fb loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), can_use_fbreg); mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); - add_loc_descr (&loc_result, - new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); + add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); for (i = 1; i < num_elem; i++) { dw_loc_descr_ref temp; @@ -8629,9 +8646,7 @@ loc_descriptor (rtx rtl, bool can_use_fb can_use_fbreg); add_loc_descr (&loc_result, temp); mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); - add_loc_descr (&loc_result, - new_loc_descr (DW_OP_piece, - GET_MODE_SIZE (mode), 0)); + add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); } } break; @@ -9930,8 +9945,7 @@ add_location_or_const_value_attribute (d /* Create the first one, so we have something to add to. */ descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), true); mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); - add_loc_descr (&descr, - new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); + add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode)); for (i = 1; i < num_elem; i++) { dw_loc_descr_ref temp; @@ -9939,9 +9953,7 @@ add_location_or_const_value_attribute (d temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), true); add_loc_descr (&descr, temp); mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); - add_loc_descr (&descr, - new_loc_descr (DW_OP_piece, - GET_MODE_SIZE (mode), 0)); + add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode)); } } add_AT_location_description (die, DW_AT_location, descr); --- gcc/var-tracking.c.jj 2005-06-07 00:39:11.000000000 +0200 +++ gcc/var-tracking.c 2005-06-07 00:52:15.000000000 +0200 @@ -102,6 +102,8 @@ #include "alloc-pool.h" #include "fibheap.h" #include "hashtab.h" +#include "regs.h" +#include "expr.h" /* Type of micro operation. */ enum micro_operation_type @@ -2185,10 +2187,12 @@ emit_note_insn_var_location (void **varp rtx insn = ((emit_note_data *)data)->insn; enum emit_note_where where = ((emit_note_data *)data)->where; rtx note; - int i; + int i, j, n_var_parts; bool complete; HOST_WIDE_INT last_limit; tree type_size_unit; + HOST_WIDE_INT offsets[MAX_VAR_PARTS]; + rtx loc[MAX_VAR_PARTS]; #ifdef ENABLE_CHECKING if (!var->decl) @@ -2197,16 +2201,90 @@ emit_note_insn_var_location (void **varp complete = true; last_limit = 0; + n_var_parts = 0; for (i = 0; i < var->n_var_parts; i++) { + enum machine_mode mode, wider_mode; + if (last_limit < var->var_part[i].offset) { complete = false; break; } - last_limit - = (var->var_part[i].offset - + GET_MODE_SIZE (GET_MODE (var->var_part[i].loc_chain->loc))); + else if (last_limit > var->var_part[i].offset) + continue; + offsets[n_var_parts] = var->var_part[i].offset; + loc[n_var_parts] = var->var_part[i].loc_chain->loc; + mode = GET_MODE (loc[n_var_parts]); + last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); + + /* Attempt to merge adjacent registers or memory. */ + wider_mode = GET_MODE_WIDER_MODE (mode); + for (j = i + 1; j < var->n_var_parts; j++) + if (last_limit <= var->var_part[j].offset) + break; + if (j < var->n_var_parts + && wider_mode != VOIDmode + && GET_CODE (loc[n_var_parts]) + == GET_CODE (var->var_part[j].loc_chain->loc) + && mode == GET_MODE (var->var_part[j].loc_chain->loc) + && last_limit == var->var_part[j].offset) + { + rtx new_loc = NULL; + rtx loc2 = var->var_part[j].loc_chain->loc; + + if (REG_P (loc[n_var_parts]) + && HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), mode) * 2 + == HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), wider_mode) + && REGNO (loc[n_var_parts]) + + HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), mode) + == REGNO (loc2)) + { + if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN) + new_loc = simplify_subreg (wider_mode, loc[n_var_parts], + mode, 0); + else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN) + new_loc = simplify_subreg (wider_mode, loc2, mode, 0); + if (new_loc) + { + if (!REG_P (new_loc) + || REGNO (new_loc) != REGNO (loc[n_var_parts])) + new_loc = NULL; + else + REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]); + } + } + else if (GET_CODE (loc[n_var_parts]) == MEM + && GET_CODE (XEXP (loc2, 0)) == PLUS + && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG + && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT) + { + if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG + && rtx_equal_p (XEXP (loc[n_var_parts], 0), + XEXP (XEXP (loc2, 0), 0)) + && INTVAL (XEXP (XEXP (loc2, 0), 1)) + == GET_MODE_SIZE (mode)) + || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS + && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1)) + == CONST_INT + && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0), + XEXP (XEXP (loc2, 0), 0)) + && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1)) + + GET_MODE_SIZE (mode) + == INTVAL (XEXP (XEXP (loc2, 0), 1)))) + new_loc = adjust_address_nv (loc[n_var_parts], + wider_mode, 0); + } + + if (new_loc) + { + loc[n_var_parts] = new_loc; + mode = wider_mode; + last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); + i = j; + } + } + ++n_var_parts; } type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl)); if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit)) @@ -2222,26 +2300,24 @@ emit_note_insn_var_location (void **varp NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, NULL_RTX); } - else if (var->n_var_parts == 1) + else if (n_var_parts == 1) { rtx expr_list - = gen_rtx_EXPR_LIST (VOIDmode, - var->var_part[0].loc_chain->loc, - GEN_INT (var->var_part[0].offset)); + = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0])); NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, expr_list); } - else if (var->n_var_parts) + else if (n_var_parts) { - rtx argp[MAX_VAR_PARTS]; rtx parallel; - for (i = 0; i < var->n_var_parts; i++) - argp[i] = gen_rtx_EXPR_LIST (VOIDmode, var->var_part[i].loc_chain->loc, - GEN_INT (var->var_part[i].offset)); + for (i = 0; i < n_var_parts; i++) + loc[i] + = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i])); + parallel = gen_rtx_PARALLEL (VOIDmode, - gen_rtvec_v (var->n_var_parts, argp)); + gen_rtvec_v (n_var_parts, loc)); NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, parallel); } --- gcc/Makefile.in.jj 2005-06-07 00:39:11.000000000 +0200 +++ gcc/Makefile.in 2005-06-07 00:55:12.000000000 +0200 @@ -1693,7 +1693,8 @@ df.o : df.c $(CONFIG_H) $(SYSTEM_H) core $(BASIC_BLOCK_H) df.h $(FIBHEAP_H) var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h flags.h \ - $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) + $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \ + $(REGS_H) $(EXPR_H) conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OBSTACK_H) \ $(HASHTAB_H) $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H) profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \