389 lines · plain
1# REQUIRES: x862# RUN: rm -rf %t; split-file %s %t3 4## Check that we fold identical function bodies correctly. Note: This test5## has many different functions; each group of similarly-named functions aim6## to test one aspect of ICF's logic. To prevent accidental folding across7## groups, we use `mov` instructions with a variety of immediates, with8## different immediate values for each group.9 10# RUN: llvm-mc -emit-compact-unwind-non-canonical=true -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/main.s -o %t/main.o11# RUN: llvm-mc -emit-compact-unwind-non-canonical=true -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/abs.s -o %t/abs.o12# RUN: %lld -lSystem --icf=all -o %t/main %t/main.o %t/abs.o13# RUN: llvm-objdump -d --syms --dwarf=frames %t/main | FileCheck %s14 15# CHECK-LABEL: SYMBOL TABLE:16# CHECK: [[#%x,ABS1B_REF:]] l F __TEXT,__text _abs1a_ref17# CHECK: [[#%x,ABS1B_REF]] l F __TEXT,__text _abs1b_ref18# CHECK: [[#%x,ABS1B_REF_WITH_ADDEND:]] l F __TEXT,__text _abs1a_ref_with_addend19# CHECK: [[#%x,ABS1B_REF_WITH_ADDEND]] l F __TEXT,__text _abs1b_ref_with_addend20# CHECK: [[#%x,ABS2_REF:]] l F __TEXT,__text _abs2_ref21# CHECK: [[#%x,NOT_ABS_REF:]] l F __TEXT,__text _not_abs_ref22# CHECK: [[#%x,DYLIB_REF_2:]] l F __TEXT,__text _dylib_ref_123# CHECK: [[#%x,DYLIB_REF_2]] l F __TEXT,__text _dylib_ref_224# CHECK: [[#%x,DYLIB_REF_3:]] l F __TEXT,__text _dylib_ref_325# CHECK: [[#%x,DYLIB_REF_4:]] l F __TEXT,__text _dylib_ref_426# CHECK: [[#%x,ALT:]] l F __TEXT,__text _alt27# CHECK: [[#%x,WITH_ALT_ENTRY:]] l F __TEXT,__text _with_alt_entry28# CHECK: [[#%x,NO_ALT_ENTRY:]] l F __TEXT,__text _no_alt_entry29# CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_2:]] l F __TEXT,__text _defined_ref_with_addend_130# CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_2]] l F __TEXT,__text _defined_ref_with_addend_231# CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_3:]] l F __TEXT,__text _defined_ref_with_addend_332# CHECK: [[#%x,RECURSIVE:]] l F __TEXT,__text _recursive33# CHECK: [[#%x,CALL_RECURSIVE_2:]] l F __TEXT,__text _call_recursive_134# CHECK: [[#%x,CALL_RECURSIVE_2]] l F __TEXT,__text _call_recursive_235# CHECK: [[#%x,CHECK_LENGTH_1:]] l F __TEXT,__text _check_length_136# CHECK: [[#%x,CHECK_LENGTH_2:]] l F __TEXT,__text _check_length_237# CHECK: [[#%x,HAS_UNWIND_2:]] l F __TEXT,__text _has_unwind_138# CHECK: [[#%x,HAS_UNWIND_2]] l F __TEXT,__text _has_unwind_239# CHECK: [[#%x,HAS_UNWIND_3:]] l F __TEXT,__text _has_unwind_340# CHECK: [[#%x,HAS_UNWIND_4:]] l F __TEXT,__text _has_unwind_441# CHECK: [[#%x,HAS_ABS_PERSONALITY_1:]] l F __TEXT,__text _has_abs_personality_142# CHECK: [[#%x,HAS_ABS_PERSONALITY_2:]] l F __TEXT,__text _has_abs_personality_243# CHECK: [[#%x,HAS_EH_FRAME_1:]] l F __TEXT,__text _has_eh_frame_144# CHECK: [[#%x,HAS_EH_FRAME_2:]] l F __TEXT,__text _has_eh_frame_245# CHECK: [[#%x,HAS_EH_FRAME_3:]] l F __TEXT,__text _has_eh_frame_346# CHECK: [[#%x,MUTALLY_RECURSIVE_2:]] l F __TEXT,__text _mutually_recursive_147# CHECK: [[#%x,MUTALLY_RECURSIVE_2]] l F __TEXT,__text _mutually_recursive_248# CHECK: [[#%x,INIT_2:]] l F __TEXT,__text _init_149# CHECK: [[#%x,INIT_2]] l F __TEXT,__text _init_250# CHECK: [[#%x,INIT_3:]] l O __TEXT,__foo _init_351### FIXME: Mutually-recursive functions with identical bodies (see below)52# COM: [[#%x,ASYMMETRIC_RECURSIVE_2:]] l F __TEXT,__text _asymmetric_recursive_153# COM: [[#%x,ASYMMETRIC_RECURSIVE_2]] l F __TEXT,__text _asymmetric_recursive_254# CHECK: [[#%x,GCC_EXCEPT_0:]] l O __TEXT,__gcc_except_tab GCC_except_table055# CHECK: [[#%x,GCC_EXCEPT_0]] l O __TEXT,__gcc_except_tab GCC_except_table156# CHECK: [[#%x,GCC_EXCEPT_2:]] l O __TEXT,__gcc_except_tab GCC_except_table257 58## Check that we don't accidentally dedup distinct EH frames.59# CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_1]]60# CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_2]]61# CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_3]]62 63# CHECK-LABEL: Disassembly of section __TEXT,__text:64# CHECK: <_main>:65# CHECK: callq 0x[[#%x,ABS1B_REF]] <_abs1b_ref>66# CHECK: callq 0x[[#%x,ABS1B_REF]] <_abs1b_ref>67# CHECK: callq 0x[[#%x,ABS1B_REF_WITH_ADDEND]] <_abs1b_ref_with_addend>68# CHECK: callq 0x[[#%x,ABS1B_REF_WITH_ADDEND]] <_abs1b_ref_with_addend>69# CHECK: callq 0x[[#%x,ABS2_REF]] <_abs2_ref>70# CHECK: callq 0x[[#%x,NOT_ABS_REF]] <_not_abs_ref>71# CHECK: callq 0x[[#%x,DYLIB_REF_2]] <_dylib_ref_2>72# CHECK: callq 0x[[#%x,DYLIB_REF_2]] <_dylib_ref_2>73# CHECK: callq 0x[[#%x,DYLIB_REF_3]] <_dylib_ref_3>74# CHECK: callq 0x[[#%x,DYLIB_REF_4]] <_dylib_ref_4>75# CHECK: callq 0x[[#%x,ALT]] <_alt>76# CHECK: callq 0x[[#%x,WITH_ALT_ENTRY]] <_with_alt_entry>77# CHECK: callq 0x[[#%x,NO_ALT_ENTRY]] <_no_alt_entry>78# CHECK: callq 0x[[#%x,DEFINED_REF_WITH_ADDEND_2]] <_defined_ref_with_addend_2>79# CHECK: callq 0x[[#%x,DEFINED_REF_WITH_ADDEND_2]] <_defined_ref_with_addend_2>80# CHECK: callq 0x[[#%x,DEFINED_REF_WITH_ADDEND_3]] <_defined_ref_with_addend_3>81# CHECK: callq 0x[[#%x,RECURSIVE]] <_recursive>82# CHECK: callq 0x[[#%x,CALL_RECURSIVE_2]] <_call_recursive_2>83# CHECK: callq 0x[[#%x,CALL_RECURSIVE_2]] <_call_recursive_2>84# CHECK: callq 0x[[#%x,CHECK_LENGTH_1]] <_check_length_1>85# CHECK: callq 0x[[#%x,CHECK_LENGTH_2]] <_check_length_2>86# CHECK: callq 0x[[#%x,HAS_UNWIND_2]] <_has_unwind_2>87# CHECK: callq 0x[[#%x,HAS_UNWIND_2]] <_has_unwind_2>88# CHECK: callq 0x[[#%x,HAS_UNWIND_3]] <_has_unwind_3>89# CHECK: callq 0x[[#%x,HAS_UNWIND_4]] <_has_unwind_4>90# CHECK: callq 0x[[#%x,HAS_ABS_PERSONALITY_1]] <_has_abs_personality_1>91# CHECK: callq 0x[[#%x,HAS_ABS_PERSONALITY_2]] <_has_abs_personality_2>92# CHECK: callq 0x[[#%x,HAS_EH_FRAME_1]] <_has_eh_frame_1>93# CHECK: callq 0x[[#%x,HAS_EH_FRAME_2]] <_has_eh_frame_2>94# CHECK: callq 0x[[#%x,HAS_EH_FRAME_3]] <_has_eh_frame_3>95# CHECK: callq 0x[[#%x,MUTALLY_RECURSIVE_2]] <_mutually_recursive_2>96# CHECK: callq 0x[[#%x,MUTALLY_RECURSIVE_2]] <_mutually_recursive_2>97## FIXME Mutually-recursive functions with identical bodies (see below)98# COM: callq 0x[[#%x,ASYMMETRIC_RECURSIVE_2]] <_asymmetric_recursive_2>99# COM: callq 0x[[#%x,ASYMMETRIC_RECURSIVE_2]] <_asymmetric_recursive_2>100# CHECK: callq 0x[[#%x,INIT_2]] <_init_2>101# CHECK: callq 0x[[#%x,INIT_2]] <_init_2>102# CHECK: callq 0x[[#%x,INIT_3]] <_init_3>103 104### TODO:105### * Fold: funcs only differ in alignment106### * No fold: func is weak? preemptible?107### * Test that we hash things appropriately w/ minimal collisions108 109#--- abs.s110.subsections_via_symbols111 112.globl _abs1a, _abs1b, _abs2, _not_abs113_abs1a = 0xfac3114_abs1b = 0xfac3115_abs2 = 0xf00d116 117.data118.space 0xfac3119## _not_abs has the same Defined::value as _abs1{a,b}120_not_abs:121 122#--- main.s123.subsections_via_symbols124.text125 126_abs1a_ref:127 movabs $_abs1a, %rdx128 129_abs1b_ref:130 movabs $_abs1b, %rdx131 132_abs1a_ref_with_addend:133 movabs $_abs1a + 3, %rdx134 135_abs1b_ref_with_addend:136 movabs $_abs1b + 3, %rdx137 138## No fold: the absolute symbol value differs139_abs2_ref:140 movabs $_abs2, %rdx141 142## No fold: _not_abs has the same value as _abs1{a,b}, but is not absolute.143_not_abs_ref:144 movabs $_not_abs, %rdx145 146_dylib_ref_1:147 mov ___nan@GOTPCREL(%rip), %rax148 callq ___isnan149 150_dylib_ref_2:151 mov ___nan@GOTPCREL(%rip), %rax152 callq ___isnan153 154## No fold: referent dylib symbol differs155_dylib_ref_3:156 mov ___inf@GOTPCREL(%rip), %rax157 callq ___inf158 159## No fold: referent dylib addend differs160_dylib_ref_4:161 mov ___nan + 1@GOTPCREL(%rip), %rax162 callq ___inf + 1163 164## Sections with alt entries cannot be merged.165.alt_entry _alt166_with_alt_entry:167 movq $3132, %rax168_alt:169 ret170 171_no_alt_entry:172 movq $3132, %rax173 ret174 175_defined_ref_with_addend_1:176 callq _with_alt_entry + 4177 178_defined_ref_with_addend_2:179 callq _with_alt_entry + 4180 181# No fold: addend differs182_defined_ref_with_addend_3:183 callq _with_alt_entry + 8184 185## _recursive has the same body as its next two callers, but cannot be folded186## with them.187_recursive:188 callq _recursive189 190_call_recursive_1:191 callq _recursive192 193_call_recursive_2:194 callq _recursive195 196## Functions of different lengths should not be folded197_check_length_1:198 movq $97, %rax199 200_check_length_2:201 movq $97, %rax202 .space 1203 204_my_personality:205 mov $1345, %rax206 207## Functions with identical unwind info should be folded.208_has_unwind_1:209 .cfi_startproc210 .cfi_personality 155, _my_personality211 .cfi_lsda 16, Lexception0212 .cfi_def_cfa_offset 16213 ret214 .cfi_endproc215 216_has_unwind_2:217 .cfi_startproc218 .cfi_personality 155, _my_personality219 .cfi_lsda 16, Lexception1220 .cfi_def_cfa_offset 16221 ret222 .cfi_endproc223 224## This function has a different cfa_offset from the first two, and therefore225## should not be folded.226_has_unwind_3:227 .cfi_startproc228 .cfi_personality 155, _my_personality229 .cfi_lsda 16, Lexception1230 .cfi_def_cfa_offset 8231 ret232 .cfi_endproc233 234## This function has a different LSDA from the first two, and therefore should235## not be folded.236_has_unwind_4:237 .cfi_startproc238 .cfi_personality 155, _my_personality239 .cfi_lsda 16, Lexception2240 .cfi_def_cfa_offset 16241 ret242 .cfi_endproc243 244## The next two functions should not be folded as they refer to personalities245## at different absolute addresses. This verifies that we are doing the right246## thing in our "data slicing hack" for compact unwind.247_has_abs_personality_1:248 .cfi_startproc249 .cfi_personality 155, _abs_personality_1250 .cfi_def_cfa_offset 16251 ret252 .cfi_endproc253 254_has_abs_personality_2:255 .cfi_startproc256 .cfi_personality 155, _abs_personality_2257 .cfi_def_cfa_offset 16258 ret259 .cfi_endproc260 261_abs_personality_1 = 0x1262_abs_personality_2 = 0x2263 264## In theory _has_eh_frame_{1, 2} can be dedup'ed, but we don't support this265## yet.266_has_eh_frame_1:267 .cfi_startproc268 .cfi_def_cfa_offset 8269 ## cfi_escape cannot be encoded in compact unwind270 .cfi_escape 0x2e, 0x10271 ret272 .cfi_endproc273 274_has_eh_frame_2:275 .cfi_startproc276 .cfi_def_cfa_offset 8277 ## cfi_escape cannot be encoded in compact unwind278 .cfi_escape 0x2e, 0x10279 ret280 .cfi_endproc281 282## The nop in this function body means that it cannot be folded with the283## previous two, even though the unwind info is otherwise identical.284_has_eh_frame_3:285 .cfi_startproc286 .cfi_def_cfa_offset 8287 ## cfi_escape cannot be encoded in compact unwind288 .cfi_escape 0x2e, 0x10289 nop290 ret291 .cfi_endproc292 293## Fold: Mutually-recursive functions with symmetric bodies294_mutually_recursive_1:295 callq _mutually_recursive_1 # call myself296 callq _mutually_recursive_2 # call my twin297 298_mutually_recursive_2:299 callq _mutually_recursive_2 # call myself300 callq _mutually_recursive_1 # call my twin301 302## Fold: Mutually-recursive functions with identical bodies303##304## FIXME: This test is currently broken. Recursive call sites have no relocs305## and the non-zero displacement field is already written to the section306## data, while non-recursive call sites use symbol relocs and section data307## contains zeros in the displacement field. Thus, ICF's equalsConstant()308## finds that the section data doesn't match.309##310## ELF folds this case properly because it emits symbol relocs for all calls,311## even recursive ones.312 313_asymmetric_recursive_1:314 callq _asymmetric_recursive_1 # call myself315 callq _asymmetric_recursive_2 # call my twin316 movl $3, %eax317 318_asymmetric_recursive_2:319 callq _asymmetric_recursive_1 # call my twin320 callq _asymmetric_recursive_2 # call myself321 movl $3, %eax322 323_init_1:324 movq $12938, %rax325 326## Fold: _init_2 is in a section that gets renamed and output as __text327.section __TEXT,__StaticInit328_init_2:329 movq $12938, %rax330 331## No fold: _init_3 is in a different output section from _init_{1,2}332.section __TEXT,__foo333_init_3:334 movq $12938, %rax335 336.text337.globl _main338_main:339 callq _abs1a_ref340 callq _abs1b_ref341 callq _abs1a_ref_with_addend342 callq _abs1b_ref_with_addend343 callq _abs2_ref344 callq _not_abs_ref345 callq _dylib_ref_1346 callq _dylib_ref_2347 callq _dylib_ref_3348 callq _dylib_ref_4349 callq _alt350 callq _with_alt_entry351 callq _no_alt_entry352 callq _defined_ref_with_addend_1353 callq _defined_ref_with_addend_2354 callq _defined_ref_with_addend_3355 callq _recursive356 callq _call_recursive_1357 callq _call_recursive_2358 callq _check_length_1359 callq _check_length_2360 callq _has_unwind_1361 callq _has_unwind_2362 callq _has_unwind_3363 callq _has_unwind_4364 callq _has_abs_personality_1365 callq _has_abs_personality_2366 callq _has_eh_frame_1367 callq _has_eh_frame_2368 callq _has_eh_frame_3369 callq _mutually_recursive_1370 callq _mutually_recursive_2371 callq _asymmetric_recursive_1372 callq _asymmetric_recursive_2373 callq _init_1374 callq _init_2375 callq _init_3376 377.section __TEXT,__gcc_except_tab378GCC_except_table0:379Lexception0:380 .byte 255381 382GCC_except_table1:383Lexception1:384 .byte 255385 386GCC_except_table2:387Lexception2:388 .byte 254389