2 # RUN: rm -rf %t; split-file %s %t
4 ## Check that we fold identical function bodies correctly. Note: This test
5 ## has many different functions; each group of similarly-named functions aim
6 ## to test one aspect of ICF's logic. To prevent accidental folding across
7 ## groups, we use `mov` instructions with a variety of immediates, with
8 ## different immediate values for each group.
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.o
11 # RUN: llvm-mc -emit-compact-unwind-non-canonical=true -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/abs.s -o %t/abs.o
12 # RUN: %lld -lSystem --icf=all -o %t/main %t/main.o %t/abs.o
13 # RUN: llvm-objdump -d --syms --dwarf=frames %t/main | FileCheck %s
15 # CHECK-LABEL: SYMBOL TABLE:
16 # CHECK: [[#%x,ABS1B_REF:]] l F __TEXT,__text _abs1a_ref
17 # CHECK: [[#%x,ABS1B_REF]] l F __TEXT,__text _abs1b_ref
18 # CHECK: [[#%x,ABS1B_REF_WITH_ADDEND:]] l F __TEXT,__text _abs1a_ref_with_addend
19 # CHECK: [[#%x,ABS1B_REF_WITH_ADDEND]] l F __TEXT,__text _abs1b_ref_with_addend
20 # CHECK: [[#%x,ABS2_REF:]] l F __TEXT,__text _abs2_ref
21 # CHECK: [[#%x,NOT_ABS_REF:]] l F __TEXT,__text _not_abs_ref
22 # CHECK: [[#%x,DYLIB_REF_2:]] l F __TEXT,__text _dylib_ref_1
23 # CHECK: [[#%x,DYLIB_REF_2]] l F __TEXT,__text _dylib_ref_2
24 # CHECK: [[#%x,DYLIB_REF_3:]] l F __TEXT,__text _dylib_ref_3
25 # CHECK: [[#%x,DYLIB_REF_4:]] l F __TEXT,__text _dylib_ref_4
26 # CHECK: [[#%x,ALT:]] l F __TEXT,__text _alt
27 # CHECK: [[#%x,WITH_ALT_ENTRY:]] l F __TEXT,__text _with_alt_entry
28 # CHECK: [[#%x,NO_ALT_ENTRY:]] l F __TEXT,__text _no_alt_entry
29 # CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_2:]] l F __TEXT,__text _defined_ref_with_addend_1
30 # CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_2]] l F __TEXT,__text _defined_ref_with_addend_2
31 # CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_3:]] l F __TEXT,__text _defined_ref_with_addend_3
32 # CHECK: [[#%x,RECURSIVE:]] l F __TEXT,__text _recursive
33 # CHECK: [[#%x,CALL_RECURSIVE_2:]] l F __TEXT,__text _call_recursive_1
34 # CHECK: [[#%x,CALL_RECURSIVE_2]] l F __TEXT,__text _call_recursive_2
35 # CHECK: [[#%x,CHECK_LENGTH_1:]] l F __TEXT,__text _check_length_1
36 # CHECK: [[#%x,CHECK_LENGTH_2:]] l F __TEXT,__text _check_length_2
37 # CHECK: [[#%x,HAS_UNWIND_2:]] l F __TEXT,__text _has_unwind_1
38 # CHECK: [[#%x,HAS_UNWIND_2]] l F __TEXT,__text _has_unwind_2
39 # CHECK: [[#%x,HAS_UNWIND_3:]] l F __TEXT,__text _has_unwind_3
40 # CHECK: [[#%x,HAS_UNWIND_4:]] l F __TEXT,__text _has_unwind_4
41 # CHECK: [[#%x,HAS_ABS_PERSONALITY_1:]] l F __TEXT,__text _has_abs_personality_1
42 # CHECK: [[#%x,HAS_ABS_PERSONALITY_2:]] l F __TEXT,__text _has_abs_personality_2
43 # CHECK: [[#%x,HAS_EH_FRAME_1:]] l F __TEXT,__text _has_eh_frame_1
44 # CHECK: [[#%x,HAS_EH_FRAME_2:]] l F __TEXT,__text _has_eh_frame_2
45 # CHECK: [[#%x,HAS_EH_FRAME_3:]] l F __TEXT,__text _has_eh_frame_3
46 # CHECK: [[#%x,MUTALLY_RECURSIVE_2:]] l F __TEXT,__text _mutually_recursive_1
47 # CHECK: [[#%x,MUTALLY_RECURSIVE_2]] l F __TEXT,__text _mutually_recursive_2
48 # CHECK: [[#%x,INIT_2:]] l F __TEXT,__text _init_1
49 # CHECK: [[#%x,INIT_2]] l F __TEXT,__text _init_2
50 # CHECK: [[#%x,INIT_3:]] l O __TEXT,__foo _init_3
51 ### FIXME: Mutually-recursive functions with identical bodies (see below)
52 # COM: [[#%x,ASYMMETRIC_RECURSIVE_2:]] l F __TEXT,__text _asymmetric_recursive_1
53 # COM: [[#%x,ASYMMETRIC_RECURSIVE_2]] l F __TEXT,__text _asymmetric_recursive_2
54 # CHECK: [[#%x,GCC_EXCEPT_0:]] l O __TEXT,__gcc_except_tab GCC_except_table0
55 # CHECK: [[#%x,GCC_EXCEPT_0]] l O __TEXT,__gcc_except_tab GCC_except_table1
56 # CHECK: [[#%x,GCC_EXCEPT_2:]] l O __TEXT,__gcc_except_tab GCC_except_table2
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]]
63 # CHECK-LABEL: Disassembly of section __TEXT,__text:
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>
105 ### * Fold: funcs only differ in alignment
106 ### * No fold: func is weak? preemptible?
107 ### * Test that we hash things appropriately w/ minimal collisions
110 .subsections_via_symbols
112 .globl _abs1a, _abs1b, _abs2, _not_abs
119 ## _not_abs has the same Defined::value as _abs1{a,b}
123 .subsections_via_symbols
132 _abs1a_ref_with_addend
:
133 movabs $_abs1a
+ 3, %rdx
135 _abs1b_ref_with_addend
:
136 movabs $_abs1b
+ 3, %rdx
138 ## No fold: the absolute symbol value differs
142 ## No fold: _not_abs has the same value as _abs1{a,b}, but is not absolute.
144 movabs $_not_abs
, %rdx
147 mov ___nan@GOTPCREL
(%rip
), %rax
151 mov ___nan@GOTPCREL
(%rip
), %rax
154 ## No fold: referent dylib symbol differs
156 mov ___inf@GOTPCREL
(%rip
), %rax
159 ## No fold: referent dylib addend differs
161 mov ___nan
+ 1@GOTPCREL
(%rip
), %rax
164 ## Sections with alt entries cannot be merged.
175 _defined_ref_with_addend_1
:
176 callq _with_alt_entry
+ 4
178 _defined_ref_with_addend_2
:
179 callq _with_alt_entry
+ 4
181 # No fold: addend differs
182 _defined_ref_with_addend_3
:
183 callq _with_alt_entry
+ 8
185 ## _recursive has the same body as its next two callers, but cannot be folded
196 ## Functions of different lengths should not be folded
207 ## Functions with identical unwind info should be folded.
210 .cfi_personality 155, _my_personality
211 .cfi_lsda 16, Lexception0
212 .cfi_def_cfa_offset 16
218 .cfi_personality 155, _my_personality
219 .cfi_lsda 16, Lexception1
220 .cfi_def_cfa_offset 16
224 ## This function has a different cfa_offset from the first two, and therefore
225 ## should not be folded.
228 .cfi_personality 155, _my_personality
229 .cfi_lsda 16, Lexception1
230 .cfi_def_cfa_offset 8
234 ## This function has a different LSDA from the first two, and therefore should
238 .cfi_personality 155, _my_personality
239 .cfi_lsda 16, Lexception2
240 .cfi_def_cfa_offset 16
244 ## The next two functions should not be folded as they refer to personalities
245 ## at different absolute addresses. This verifies that we are doing the right
246 ## thing in our "data slicing hack" for compact unwind.
247 _has_abs_personality_1
:
249 .cfi_personality 155, _abs_personality_1
250 .cfi_def_cfa_offset 16
254 _has_abs_personality_2
:
256 .cfi_personality 155, _abs_personality_2
257 .cfi_def_cfa_offset 16
261 _abs_personality_1
= 0x1
262 _abs_personality_2
= 0x2
264 ## In theory _has_eh_frame_{1, 2} can be dedup'ed, but we don't support this
268 .cfi_def_cfa_offset 8
269 ## cfi_escape cannot be encoded in compact unwind
270 .cfi_escape 0x2e, 0x10
276 .cfi_def_cfa_offset 8
277 ## cfi_escape cannot be encoded in compact unwind
278 .cfi_escape 0x2e, 0x10
282 ## The nop in this function body means that it cannot be folded with the
283 ## previous two, even though the unwind info is otherwise identical.
286 .cfi_def_cfa_offset 8
287 ## cfi_escape cannot be encoded in compact unwind
288 .cfi_escape 0x2e, 0x10
293 ## Fold: Mutually-recursive functions with symmetric bodies
294 _mutually_recursive_1
:
295 callq _mutually_recursive_1
# call myself
296 callq _mutually_recursive_2
# call my twin
298 _mutually_recursive_2
:
299 callq _mutually_recursive_2
# call myself
300 callq _mutually_recursive_1
# call my twin
302 ## Fold: Mutually-recursive functions with identical bodies
304 ## FIXME: This test is currently broken. Recursive call sites have no relocs
305 ## and the non-zero displacement field is already written to the section
306 ## data, while non-recursive call sites use symbol relocs and section data
307 ## contains zeros in the displacement field. Thus, ICF's equalsConstant()
308 ## finds that the section data doesn't match.
310 ## ELF folds this case properly because it emits symbol relocs for all calls,
311 ## even recursive ones.
313 _asymmetric_recursive_1
:
314 callq _asymmetric_recursive_1
# call myself
315 callq _asymmetric_recursive_2
# call my twin
318 _asymmetric_recursive_2
:
319 callq _asymmetric_recursive_1
# call my twin
320 callq _asymmetric_recursive_2
# call myself
326 ## Fold: _init_2 is in a section that gets renamed and output as __text
327 .section __TEXT,__StaticInit
331 ## No fold: _init_3 is in a different output section from _init_{1,2}
332 .section __TEXT,__foo
341 callq _abs1a_ref_with_addend
342 callq _abs1b_ref_with_addend
350 callq _with_alt_entry
352 callq _defined_ref_with_addend_1
353 callq _defined_ref_with_addend_2
354 callq _defined_ref_with_addend_3
356 callq _call_recursive_1
357 callq _call_recursive_2
358 callq _check_length_1
359 callq _check_length_2
364 callq _has_abs_personality_1
365 callq _has_abs_personality_2
366 callq _has_eh_frame_1
367 callq _has_eh_frame_2
368 callq _has_eh_frame_3
369 callq _mutually_recursive_1
370 callq _mutually_recursive_2
371 callq _asymmetric_recursive_1
372 callq _asymmetric_recursive_2
377 .section __TEXT,__gcc_except_tab