1# REQUIRES: x86 2# RUN: rm -rf %t; split-file %s %t 3 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. 9 10# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/main.s -o %t/main.o 11# RUN: llvm-mc -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 14 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,WITH_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 57 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,WITH_ALT_ENTRY]] <_with_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 alignment 106### * No fold: func is weak? preemptible? 107### * Test that we hash things appropriately w/ minimal collisions 108 109#--- abs.s 110.subsections_via_symbols 111 112.globl _abs1a, _abs1b, _abs2, _not_abs 113_abs1a = 0xfac3 114_abs1b = 0xfac3 115_abs2 = 0xf00d 116 117.data 118.space 0xfac3 119## _not_abs has the same Defined::value as _abs1{a,b} 120_not_abs: 121 122#--- main.s 123.subsections_via_symbols 124.text 125 126_abs1a_ref: 127 movabs $_abs1a, %rdx 128 129_abs1b_ref: 130 movabs $_abs1b, %rdx 131 132_abs1a_ref_with_addend: 133 movabs $_abs1a + 3, %rdx 134 135_abs1b_ref_with_addend: 136 movabs $_abs1b + 3, %rdx 137 138## No fold: the absolute symbol value differs 139_abs2_ref: 140 movabs $_abs2, %rdx 141 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, %rdx 145 146_dylib_ref_1: 147 mov ___nan@GOTPCREL(%rip), %rax 148 callq ___isnan 149 150_dylib_ref_2: 151 mov ___nan@GOTPCREL(%rip), %rax 152 callq ___isnan 153 154## No fold: referent dylib symbol differs 155_dylib_ref_3: 156 mov ___inf@GOTPCREL(%rip), %rax 157 callq ___inf 158 159## No fold: referent dylib addend differs 160_dylib_ref_4: 161 mov ___nan + 1@GOTPCREL(%rip), %rax 162 callq ___inf + 1 163 164## We can merge two sections even if one of them has an alt entry. Just make 165## sure we don't merge the alt entry symbol with a regular symbol. 166.alt_entry _alt 167_with_alt_entry: 168 movq $3132, %rax 169_alt: 170 ret 171 172_no_alt_entry: 173 movq $3132, %rax 174 ret 175 176_defined_ref_with_addend_1: 177 callq _with_alt_entry + 4 178 179_defined_ref_with_addend_2: 180 callq _with_alt_entry + 4 181 182# No fold: addend differs 183_defined_ref_with_addend_3: 184 callq _with_alt_entry + 8 185 186## _recursive has the same body as its next two callers, but cannot be folded 187## with them. 188_recursive: 189 callq _recursive 190 191_call_recursive_1: 192 callq _recursive 193 194_call_recursive_2: 195 callq _recursive 196 197## Functions of different lengths should not be folded 198_check_length_1: 199 movq $97, %rax 200 201_check_length_2: 202 movq $97, %rax 203 .space 1 204 205_my_personality: 206 mov $1345, %rax 207 208## Functions with identical unwind info should be folded. 209_has_unwind_1: 210 .cfi_startproc 211 .cfi_personality 155, _my_personality 212 .cfi_lsda 16, Lexception0 213 .cfi_def_cfa_offset 16 214 ret 215 .cfi_endproc 216 217_has_unwind_2: 218 .cfi_startproc 219 .cfi_personality 155, _my_personality 220 .cfi_lsda 16, Lexception1 221 .cfi_def_cfa_offset 16 222 ret 223 .cfi_endproc 224 225## This function has a different cfa_offset from the first two, and therefore 226## should not be folded. 227_has_unwind_3: 228 .cfi_startproc 229 .cfi_personality 155, _my_personality 230 .cfi_lsda 16, Lexception1 231 .cfi_def_cfa_offset 8 232 ret 233 .cfi_endproc 234 235## This function has a different LSDA from the first two, and therefore should 236## not be folded. 237_has_unwind_4: 238 .cfi_startproc 239 .cfi_personality 155, _my_personality 240 .cfi_lsda 16, Lexception2 241 .cfi_def_cfa_offset 16 242 ret 243 .cfi_endproc 244 245## The next two functions should not be folded as they refer to personalities 246## at different absolute addresses. This verifies that we are doing the right 247## thing in our "data slicing hack" for compact unwind. 248_has_abs_personality_1: 249 .cfi_startproc 250 .cfi_personality 155, _abs_personality_1 251 .cfi_def_cfa_offset 16 252 ret 253 .cfi_endproc 254 255_has_abs_personality_2: 256 .cfi_startproc 257 .cfi_personality 155, _abs_personality_2 258 .cfi_def_cfa_offset 16 259 ret 260 .cfi_endproc 261 262_abs_personality_1 = 0x1 263_abs_personality_2 = 0x2 264 265## In theory _has_eh_frame_{1, 2} can be dedup'ed, but we don't support this 266## yet. 267_has_eh_frame_1: 268 .cfi_startproc 269 .cfi_def_cfa_offset 8 270 ## cfi_escape cannot be encoded in compact unwind 271 .cfi_escape 0x2e, 0x10 272 ret 273 .cfi_endproc 274 275_has_eh_frame_2: 276 .cfi_startproc 277 .cfi_def_cfa_offset 8 278 ## cfi_escape cannot be encoded in compact unwind 279 .cfi_escape 0x2e, 0x10 280 ret 281 .cfi_endproc 282 283## The nop in this function body means that it cannot be folded with the 284## previous two, even though the unwind info is otherwise identical. 285_has_eh_frame_3: 286 .cfi_startproc 287 .cfi_def_cfa_offset 8 288 ## cfi_escape cannot be encoded in compact unwind 289 .cfi_escape 0x2e, 0x10 290 nop 291 ret 292 .cfi_endproc 293 294## Fold: Mutually-recursive functions with symmetric bodies 295_mutually_recursive_1: 296 callq _mutually_recursive_1 # call myself 297 callq _mutually_recursive_2 # call my twin 298 299_mutually_recursive_2: 300 callq _mutually_recursive_2 # call myself 301 callq _mutually_recursive_1 # call my twin 302 303## Fold: Mutually-recursive functions with identical bodies 304## 305## FIXME: This test is currently broken. Recursive call sites have no relocs 306## and the non-zero displacement field is already written to the section 307## data, while non-recursive call sites use symbol relocs and section data 308## contains zeros in the displacement field. Thus, ICF's equalsConstant() 309## finds that the section data doesn't match. 310## 311## ELF folds this case properly because it emits symbol relocs for all calls, 312## even recursive ones. 313 314_asymmetric_recursive_1: 315 callq _asymmetric_recursive_1 # call myself 316 callq _asymmetric_recursive_2 # call my twin 317 movl $3, %eax 318 319_asymmetric_recursive_2: 320 callq _asymmetric_recursive_1 # call my twin 321 callq _asymmetric_recursive_2 # call myself 322 movl $3, %eax 323 324_init_1: 325 movq $12938, %rax 326 327## Fold: _init_2 is in a section that gets renamed and output as __text 328.section __TEXT,__StaticInit 329_init_2: 330 movq $12938, %rax 331 332## No fold: _init_3 is in a different output section from _init_{1,2} 333.section __TEXT,__foo 334_init_3: 335 movq $12938, %rax 336 337.text 338.globl _main 339_main: 340 callq _abs1a_ref 341 callq _abs1b_ref 342 callq _abs1a_ref_with_addend 343 callq _abs1b_ref_with_addend 344 callq _abs2_ref 345 callq _not_abs_ref 346 callq _dylib_ref_1 347 callq _dylib_ref_2 348 callq _dylib_ref_3 349 callq _dylib_ref_4 350 callq _alt 351 callq _with_alt_entry 352 callq _no_alt_entry 353 callq _defined_ref_with_addend_1 354 callq _defined_ref_with_addend_2 355 callq _defined_ref_with_addend_3 356 callq _recursive 357 callq _call_recursive_1 358 callq _call_recursive_2 359 callq _check_length_1 360 callq _check_length_2 361 callq _has_unwind_1 362 callq _has_unwind_2 363 callq _has_unwind_3 364 callq _has_unwind_4 365 callq _has_abs_personality_1 366 callq _has_abs_personality_2 367 callq _has_eh_frame_1 368 callq _has_eh_frame_2 369 callq _has_eh_frame_3 370 callq _mutually_recursive_1 371 callq _mutually_recursive_2 372 callq _asymmetric_recursive_1 373 callq _asymmetric_recursive_2 374 callq _init_1 375 callq _init_2 376 callq _init_3 377 378.section __TEXT,__gcc_except_tab 379GCC_except_table0: 380Lexception0: 381 .byte 255 382 383GCC_except_table1: 384Lexception1: 385 .byte 255 386 387GCC_except_table2: 388Lexception2: 389 .byte 254 390