diff options
author | Jakub Jelinek <jakub@redhat.com> | 2011-05-31 21:15:13 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2011-05-31 21:15:13 +0200 |
commit | ead7c399bc1b0c62bacaf845628ab72024838085 (patch) | |
tree | b2319ac7f65366524c7b8737d47793fce8a175cb | |
parent | 509f4495ee4dedc2a27f9f8f749a0507ef3f1938 (diff) | |
download | gcc-ead7c399bc1b0c62bacaf845628ab72024838085.zip gcc-ead7c399bc1b0c62bacaf845628ab72024838085.tar.gz gcc-ead7c399bc1b0c62bacaf845628ab72024838085.tar.bz2 |
dwarf2out.c (resolve_addr_in_expr): Optimize away redundant DW_OP_GNU_convert ops.
* dwarf2out.c (resolve_addr_in_expr): Optimize away redundant
DW_OP_GNU_convert ops.
From-SVN: r174509
-rw-r--r-- | gcc/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 89 |
2 files changed, 78 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ed0fb81..8d6dc36a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,8 @@ 2011-05-31 Jakub Jelinek <jakub@redhat.com> + * dwarf2out.c (resolve_addr_in_expr): Optimize away redundant + DW_OP_GNU_convert ops. + * cselib.c (promote_debug_loc): Allow l->next non-NULL for cselib_preserve_constants. (cselib_lookup_1): If cselib_preserve_constants, diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 58a622c..464de16 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -24100,23 +24100,84 @@ resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED) static bool resolve_addr_in_expr (dw_loc_descr_ref loc) { + dw_loc_descr_ref keep = NULL; for (; loc; loc = loc->dw_loc_next) - if (((loc->dw_loc_opc == DW_OP_addr || loc->dtprel) - && resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL)) - || (loc->dw_loc_opc == DW_OP_implicit_value - && loc->dw_loc_oprnd2.val_class == dw_val_class_addr - && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL))) - return false; - else if (loc->dw_loc_opc == DW_OP_GNU_implicit_pointer - && loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref) + switch (loc->dw_loc_opc) { - dw_die_ref ref - = lookup_decl_die (loc->dw_loc_oprnd1.v.val_decl_ref); - if (ref == NULL) + case DW_OP_addr: + if (resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL)) + return false; + break; + case DW_OP_const4u: + case DW_OP_const8u: + if (loc->dtprel + && resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL)) + return false; + break; + case DW_OP_implicit_value: + if (loc->dw_loc_oprnd2.val_class == dw_val_class_addr + && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL)) return false; - loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref; - loc->dw_loc_oprnd1.v.val_die_ref.die = ref; - loc->dw_loc_oprnd1.v.val_die_ref.external = 0; + break; + case DW_OP_GNU_implicit_pointer: + if (loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref) + { + dw_die_ref ref + = lookup_decl_die (loc->dw_loc_oprnd1.v.val_decl_ref); + if (ref == NULL) + return false; + loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + loc->dw_loc_oprnd1.v.val_die_ref.die = ref; + loc->dw_loc_oprnd1.v.val_die_ref.external = 0; + } + break; + case DW_OP_GNU_const_type: + case DW_OP_GNU_regval_type: + case DW_OP_GNU_deref_type: + case DW_OP_GNU_convert: + case DW_OP_GNU_reinterpret: + while (loc->dw_loc_next + && loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_convert) + { + dw_die_ref base1, base2; + unsigned enc1, enc2, size1, size2; + if (loc->dw_loc_opc == DW_OP_GNU_regval_type + || loc->dw_loc_opc == DW_OP_GNU_deref_type) + base1 = loc->dw_loc_oprnd2.v.val_die_ref.die; + else + base1 = loc->dw_loc_oprnd1.v.val_die_ref.die; + base2 = loc->dw_loc_next->dw_loc_oprnd1.v.val_die_ref.die; + gcc_assert (base1->die_tag == DW_TAG_base_type + && base2->die_tag == DW_TAG_base_type); + enc1 = get_AT_unsigned (base1, DW_AT_encoding); + enc2 = get_AT_unsigned (base2, DW_AT_encoding); + size1 = get_AT_unsigned (base1, DW_AT_byte_size); + size2 = get_AT_unsigned (base2, DW_AT_byte_size); + if (size1 == size2 + && (((enc1 == DW_ATE_unsigned || enc1 == DW_ATE_signed) + && (enc2 == DW_ATE_unsigned || enc2 == DW_ATE_signed) + && loc != keep) + || enc1 == enc2)) + { + /* Optimize away next DW_OP_GNU_convert after + adjusting LOC's base type die reference. */ + if (loc->dw_loc_opc == DW_OP_GNU_regval_type + || loc->dw_loc_opc == DW_OP_GNU_deref_type) + loc->dw_loc_oprnd2.v.val_die_ref.die = base2; + else + loc->dw_loc_oprnd1.v.val_die_ref.die = base2; + loc->dw_loc_next = loc->dw_loc_next->dw_loc_next; + continue; + } + /* Don't change integer DW_OP_GNU_convert after e.g. floating + point typed stack entry. */ + else if (enc1 != DW_ATE_unsigned && enc1 != DW_ATE_signed) + keep = loc; + break; + } + break; + default: + break; } return true; } |