From: H.J. Lu Date: Thu, 7 May 2015 16:13:39 +0000 (-0700) Subject: Optimize branches to non-weak symbols with visibility X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b084df0b8d1262fb1e969c74bcc5c61e262a6199;p=binutils-gdb.git Optimize branches to non-weak symbols with visibility Branches to global non-weak symbols defined in the same segment with non-default visibility can be optimized the same way as branches to local symbols. gas/ * config/tc-i386.c (elf_symbol_resolved_in_segment_p): New. (md_estimate_size_before_relax): Use it. gas/testsuite/ * gas/i386/i386.exp: Run relax-3 and x86-64-relax-2. * gas/i386/relax-3.d: New file. * gas/i386/relax-3.s: Likewise. * gas/i386/x86-64-relax-2.d: Likewise. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 7f42a641308..9758e72b605 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +2015-05-07 H.J. Lu + + * config/tc-i386.c (elf_symbol_resolved_in_segment_p): New. + (md_estimate_size_before_relax): Use it. + 2015-05-06 Jose E. Marchesi * config/tc-sparc.c: Typo in comment fixed. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 50f9cb47ea3..c4ba13dab4d 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -8772,6 +8772,25 @@ i386_frag_max_var (fragS *frag) return TYPE_FROM_RELAX_STATE (frag->fr_subtype) == UNCOND_JUMP ? 4 : 5; } +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) +static int +elf_symbol_resolved_in_segment_p (symbolS *fr_symbol) +{ + /* STT_GNU_IFUNC symbol must go through PLT. */ + if ((symbol_get_bfdsym (fr_symbol)->flags + & BSF_GNU_INDIRECT_FUNCTION) != 0) + return 0; + + if (!S_IS_EXTERNAL (fr_symbol)) + /* Symbol may be weak or local. */ + return !S_IS_WEAK (fr_symbol); + + /* Global symbols with default visibility in a shared library may be + preempted by another definition. */ + return ELF_ST_VISIBILITY (S_GET_OTHER (fr_symbol)) != STV_DEFAULT; +} +#endif + /* md_estimate_size_before_relax() Called just before relax() for rs_machine_dependent frags. The x86 @@ -8795,10 +8814,7 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) if (S_GET_SEGMENT (fragP->fr_symbol) != segment #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || (IS_ELF - && (S_IS_EXTERNAL (fragP->fr_symbol) - || S_IS_WEAK (fragP->fr_symbol) - || ((symbol_get_bfdsym (fragP->fr_symbol)->flags - & BSF_GNU_INDIRECT_FUNCTION)))) + && !elf_symbol_resolved_in_segment_p (fragP->fr_symbol)) #endif #if defined (OBJ_COFF) && defined (TE_PE) || (OUTPUT_FLAVOR == bfd_target_coff_flavour diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 6339bff8640..1cfa5772151 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-05-07 H.J. Lu + + * gas/i386/i386.exp: Run relax-3 and x86-64-relax-2. + * gas/i386/relax-3.d: New file. + * gas/i386/relax-3.s: Likewise. + * gas/i386/x86-64-relax-2.d: Likewise. + 2015-05-06 Jose E. Marchesi * gas/sparc/natural-32.d: Test ldn, ldna, stn, stna, slln, srln, diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index e1fdd182254..af56c263991 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -394,6 +394,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] run_dump_test "size-4" run_dump_test "note" + + run_dump_test "relax-3" } # This is a PE specific test. @@ -748,6 +750,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t run_dump_test "x86-64-size-4" run_dump_test "x86-64-size-5" run_list_test "x86-64-size-inval-1" "-al" + + run_dump_test "x86-64-relax-2" } set ASFLAGS "$old_ASFLAGS" diff --git a/gas/testsuite/gas/i386/relax-3.d b/gas/testsuite/gas/i386/relax-3.d new file mode 100644 index 00000000000..8aa94e97fec --- /dev/null +++ b/gas/testsuite/gas/i386/relax-3.d @@ -0,0 +1,30 @@ +#objdump: -dwr + +.*: +file format .* + +Disassembly of section .text: + +0+ : +[ ]*[a-f0-9]+: eb 1f jmp 21 +[ ]*[a-f0-9]+: eb 19 jmp 1d +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 5 5: (R_386_PC)?(DISP)?32 global_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp a a: (R_386_PC)?(DISP)?32 weak_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp f f: (R_386_PC)?(DISP)?32 weak_hidden_undef +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 14 14: (R_386_PC)?(DISP)?32 weak_hidden_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 19 19: (R_386_PC)?(DISP)?32 hidden_undef + +0+1d : +[ ]*[a-f0-9]+: c3 ret + +0+1e : +[ ]*[a-f0-9]+: c3 ret + +0+1f : +[ ]*[a-f0-9]+: c3 ret + +0+20 : +[ ]*[a-f0-9]+: c3 ret + +0+21 : +[ ]*[a-f0-9]+: c3 ret +#pass diff --git a/gas/testsuite/gas/i386/relax-3.s b/gas/testsuite/gas/i386/relax-3.s new file mode 100644 index 00000000000..ab521854f0b --- /dev/null +++ b/gas/testsuite/gas/i386/relax-3.s @@ -0,0 +1,39 @@ + .text + .global foo +foo: + jmp local + jmp hidden_def + jmp global_def + jmp weak_def + jmp weak_hidden_undef + jmp weak_hidden_def + jmp hidden_undef + + .hidden hidden_undef + + .global hidden_def + .hidden hidden_def +hidden_def: + ret + + .global weak_hidden_def + .hidden weak_hidden_def + .weak weak_hidden_def +weak_hidden_def: + ret + + .global global_def +global_def: + ret + + .global weak_def + .weak weak_def +weak_def: + ret + +local: + ret + + .global weak_hidden_undef + .weak weak_hidden_undef + .hidden weak_hidden_undef diff --git a/gas/testsuite/gas/i386/x86-64-relax-2.d b/gas/testsuite/gas/i386/x86-64-relax-2.d new file mode 100644 index 00000000000..7b0bd567b6a --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-relax-2.d @@ -0,0 +1,32 @@ +#source: relax-3.s +#objdump: -dwr + +.*: +file format .* + + +Disassembly of section .text: + +0+ : +[ ]*[a-f0-9]+: eb 1f jmp 21 +[ ]*[a-f0-9]+: eb 19 jmp 1d +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 9 5: R_X86_64_PC32 global_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq e a: R_X86_64_PC32 weak_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 13 f: R_X86_64_PC32 weak_hidden_undef-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 18 14: R_X86_64_PC32 weak_hidden_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1d 19: R_X86_64_PC32 hidden_undef-0x4 + +0+1d : +[ ]*[a-f0-9]+: c3 retq + +0+1e : +[ ]*[a-f0-9]+: c3 retq + +0+1f : +[ ]*[a-f0-9]+: c3 retq + +0+20 : +[ ]*[a-f0-9]+: c3 retq + +0+21 : +[ ]*[a-f0-9]+: c3 retq +#pass