[lld] 8eac5dc - [lld-macho] Reorganize + extend ICF test

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 23 08:49:13 PDT 2021


Author: Jez Ng
Date: 2021-07-23T11:49:00-04:00
New Revision: 8eac5dcb36ddbb66dff467eda3fc0eee31d73631

URL: https://github.com/llvm/llvm-project/commit/8eac5dcb36ddbb66dff467eda3fc0eee31d73631
DIFF: https://github.com/llvm/llvm-project/commit/8eac5dcb36ddbb66dff467eda3fc0eee31d73631.diff

LOG: [lld-macho] Reorganize + extend ICF test

I found icf.s a bit hard to work with as it was not possible to
extend any of the functions `_a` ... `_k` to test new relocation /
referent types without modifying every single one of them. Additionally,
their one-letter names were not descriptive (though the comments
helped).

I've renamed all the functions to reflect the feature they are testing,
and shrunk them so that they contain just enough to test that one
feature.

I've also added tests for non-zero addends (via the
`_abs1a_ref_with_addend` and `_defined_ref_with_addend_1` functions).

Reviewed By: #lld-macho, gkm

Differential Revision: https://reviews.llvm.org/D106211

Added: 
    

Modified: 
    lld/test/MachO/icf.s

Removed: 
    


################################################################################
diff  --git a/lld/test/MachO/icf.s b/lld/test/MachO/icf.s
index 04b56768d21a..2fc24052e9f0 100644
--- a/lld/test/MachO/icf.s
+++ b/lld/test/MachO/icf.s
@@ -1,60 +1,79 @@
 # REQUIRES: x86
 # RUN: rm -rf %t; split-file %s %t
 
+## Check that we fold identical function bodies correctly. Note: This test
+## has many 
diff erent functions; each group of similarly-named functions aim
+## to test one aspect of ICF's logic. To prevent accidental folding across
+## groups, we use `mov` instructions with a variety of immediates, with
+## 
diff erent immediate values for each group.
+
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/main.s -o %t/main.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/abs.s -o %t/abs.o
 # RUN: %lld -lSystem --icf=all -o %t/main %t/main.o %t/abs.o
 # RUN: llvm-objdump -d --syms %t/main | FileCheck %s
 
 # CHECK-LABEL: SYMBOL TABLE:
-# CHECK:       [[#%x,MAIN:]] g   F __TEXT,__text _main
-# CHECK:       [[#%x,A:]]    g   F __TEXT,__text _a1
-# CHECK:       [[#%x,H:]]    g   F __TEXT,__text _h
-# CHECK:       [[#%x,A]]     g   F __TEXT,__text _a2
-# CHECK:       [[#%x,A]]     g   F __TEXT,__text _a3
-# CHECK:       [[#%x,B:]]    g   F __TEXT,__text _b
-# CHECK:       [[#%x,B2:]]   g   F __TEXT,__text _b2
-# CHECK:       [[#%x,C:]]    g   F __TEXT,__text _c
-# CHECK:       [[#%x,D:]]    g   F __TEXT,__text _d
-# CHECK:       [[#%x,E:]]    g   F __TEXT,__text _e
-# CHECK:       [[#%x,F:]]    g   F __TEXT,__text _f
-# CHECK:       [[#%x,G:]]    g   F __TEXT,__text _g
-# CHECK:       [[#%x,I:]]    g   F __TEXT,__text _i
-# CHECK:       [[#%x,J:]]    g   F __TEXT,__text _j
-# CHECK:       [[#%x,SR:]]   g   F __TEXT,__text _sr1
-# CHECK:       [[#%x,SR]]    g   F __TEXT,__text _sr2
-# CHECK:       [[#%x,MR:]]   g   F __TEXT,__text _mr1
-# CHECK:       [[#%x,MR]]    g   F __TEXT,__text _mr2
-# CHECK:       [[#%x,K1:]]   g   O __TEXT,__foo  _k1
-# CHECK:       [[#%x,A:]]    g   F __TEXT,__text _k2
+# CHECK: [[#%x,ABS1B_REF:]]                 l     F __TEXT,__text _abs1a_ref
+# CHECK: [[#%x,ABS1B_REF:]]                 l     F __TEXT,__text _abs1b_ref
+# CHECK: [[#%x,ABS1B_REF_WITH_ADDEND:]]     l     F __TEXT,__text _abs1a_ref_with_addend
+# CHECK: [[#%x,ABS1B_REF_WITH_ADDEND:]]     l     F __TEXT,__text _abs1b_ref_with_addend
+# CHECK: [[#%x,ABS2_REF:]]                  l     F __TEXT,__text _abs2_ref
+# CHECK: [[#%x,NOT_ABS_REF:]]               l     F __TEXT,__text _not_abs_ref
+# CHECK: [[#%x,DYLIB_REF_2:]]               l     F __TEXT,__text _dylib_ref_1
+# CHECK: [[#%x,DYLIB_REF_2:]]               l     F __TEXT,__text _dylib_ref_2
+# CHECK: [[#%x,DYLIB_REF_3:]]               l     F __TEXT,__text _dylib_ref_3
+# CHECK: [[#%x,ALT:]]                       l     F __TEXT,__text _alt
+# CHECK: [[#%x,WITH_ALT_ENTRY:]]            l     F __TEXT,__text _with_alt_entry
+# CHECK: [[#%x,WITH_ALT_ENTRY:]]            l     F __TEXT,__text _no_alt_entry
+# CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_2:]] l     F __TEXT,__text _defined_ref_with_addend_1
+# CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_2:]] l     F __TEXT,__text _defined_ref_with_addend_2
+# CHECK: [[#%x,RECURSIVE:]]                 l     F __TEXT,__text _recursive
+# CHECK: [[#%x,CALL_RECURSIVE_2:]]          l     F __TEXT,__text _call_recursive_1
+# CHECK: [[#%x,CALL_RECURSIVE_2:]]          l     F __TEXT,__text _call_recursive_2
+# CHECK: [[#%x,CHECK_LENGTH_1:]]            l     F __TEXT,__text _check_length_1
+# CHECK: [[#%x,CHECK_LENGTH_2:]]            l     F __TEXT,__text _check_length_2
+# CHECK: [[#%x,HAS_UNWIND_1:]]              l     F __TEXT,__text _has_unwind_1
+# CHECK: [[#%x,HAS_UNWIND_2:]]              l     F __TEXT,__text _has_unwind_2
+# CHECK: [[#%x,MUTALLY_RECURSIVE_2:]]       l     F __TEXT,__text _mutually_recursive_1
+# CHECK: [[#%x,MUTALLY_RECURSIVE_2:]]       l     F __TEXT,__text _mutually_recursive_2
+# CHECK: [[#%x,INIT_2:]]                    l     F __TEXT,__text _init_1
+# CHECK: [[#%x,INIT_2:]]                    l     F __TEXT,__text _init_2
+# CHECK: [[#%x,INIT_3:]]                    l     O __TEXT,__foo  _init_3
 ### FIXME: Mutually-recursive functions with identical bodies (see below)
-# COM:         [[#%x,XR:]]   g   F __TEXT,__text _xr1
-# COM:         [[#%x,XR]]    g   F __TEXT,__text _xr2
+# COM:   [[#%x,ASYMMETRIC_RECURSIVE_2:]]    l   F __TEXT,__text _asymmetric_recursive_1
+# COM:   [[#%x,ASYMMETRIC_RECURSIVE_2]]     l   F __TEXT,__text _asymmetric_recursive_2
 
 # CHECK-LABEL: Disassembly of section __TEXT,__text:
-# CHECK:       [[#%x,MAIN]] <_main>:
-# CHECK-NEXT:  callq 0x[[#%x,A]]  <_k2>
-# CHECK-NEXT:  callq 0x[[#%x,A]]  <_k2>
-# CHECK-NEXT:  callq 0x[[#%x,A]]  <_k2>
-# CHECK-NEXT:  callq 0x[[#%x,B]]  <_b>
-# CHECK-NEXT:  callq 0x[[#%x,B2]] <_b2>
-# CHECK-NEXT:  callq 0x[[#%x,C]]  <_c>
-# CHECK-NEXT:  callq 0x[[#%x,D]]  <_d>
-# CHECK-NEXT:  callq 0x[[#%x,E]]  <_e>
-# CHECK-NEXT:  callq 0x[[#%x,F]]  <_f>
-# CHECK-NEXT:  callq 0x[[#%x,G]]  <_g>
-# CHECK-NEXT:  callq 0x[[#%x,H]]  <_h>
-# CHECK-NEXT:  callq 0x[[#%x,I]]  <_i>
-# CHECK-NEXT:  callq 0x[[#%x,J]]  <_j>
-# CHECK-NEXT:  callq 0x[[#%x,K1]] <_k1>
-# CHECK-NEXT:  callq 0x[[#%x,A]]  <_k2>
-# CHECK-NEXT:  callq 0x[[#%x,SR]] <_sr2>
-# CHECK-NEXT:  callq 0x[[#%x,SR]] <_sr2>
-# CHECK-NEXT:  callq 0x[[#%x,MR]] <_mr2>
-# CHECK-NEXT:  callq 0x[[#%x,MR]] <_mr2>
-### FIXME: Mutually-recursive functions with identical bodies (see below)
-# COM-NEXT:    callq 0x[[#%x,XR]] <_xr2>
-# COM-NEXT:    callq 0x[[#%x,XR]] <_xr2>
+# CHECK:        <_main>:
+# CHECK: callq 0x[[#%x,ABS1B_REF:]]                 <_abs1b_ref>
+# CHECK: callq 0x[[#%x,ABS1B_REF:]]                 <_abs1b_ref>
+# CHECK: callq 0x[[#%x,ABS1B_REF_WITH_ADDEND:]]     <_abs1b_ref_with_addend>
+# CHECK: callq 0x[[#%x,ABS1B_REF_WITH_ADDEND:]]     <_abs1b_ref_with_addend>
+# CHECK: callq 0x[[#%x,ABS2_REF:]]                  <_abs2_ref>
+# CHECK: callq 0x[[#%x,NOT_ABS_REF:]]               <_not_abs_ref>
+# CHECK: callq 0x[[#%x,DYLIB_REF_2:]]               <_dylib_ref_2>
+# CHECK: callq 0x[[#%x,DYLIB_REF_2:]]               <_dylib_ref_2>
+# CHECK: callq 0x[[#%x,DYLIB_REF_3:]]               <_dylib_ref_3>
+# CHECK: callq 0x[[#%x,ALT:]]                       <_alt>
+# CHECK: callq 0x[[#%x,WITH_ALT_ENTRY:]]            <_with_alt_entry>
+# CHECK: callq 0x[[#%x,WITH_ALT_ENTRY:]]            <_with_alt_entry>
+# CHECK: callq 0x[[#%x,DEFINED_REF_WITH_ADDEND_2:]] <_defined_ref_with_addend_2>
+# CHECK: callq 0x[[#%x,DEFINED_REF_WITH_ADDEND_2:]] <_defined_ref_with_addend_2>
+# CHECK: callq 0x[[#%x,RECURSIVE:]]                 <_recursive>
+# CHECK: callq 0x[[#%x,CALL_RECURSIVE_2:]]          <_call_recursive_2>
+# CHECK: callq 0x[[#%x,CALL_RECURSIVE_2:]]          <_call_recursive_2>
+# CHECK: callq 0x[[#%x,CHECK_LENGTH_1:]]            <_check_length_1>
+# CHECK: callq 0x[[#%x,CHECK_LENGTH_2:]]            <_check_length_2>
+# CHECK: callq 0x[[#%x,HAS_UNWIND_1:]]              <_has_unwind_1>
+# CHECK: callq 0x[[#%x,HAS_UNWIND_2:]]              <_has_unwind_2>
+# CHECK: callq 0x[[#%x,MUTALLY_RECURSIVE_2:]]       <_mutually_recursive_2>
+# CHECK: callq 0x[[#%x,MUTALLY_RECURSIVE_2:]]       <_mutually_recursive_2>
+## FIXME: Mutually-recursive functions with identical bodies (see below)
+# COM:   callq 0x[[#%x,ASYMMETRIC_RECURSIVE_2]]     <_asymmetric_recursive_2>
+# COM:   callq 0x[[#%x,ASYMMETRIC_RECURSIVE_2]]     <_asymmetric_recursive_2>
+# CHECK: callq 0x[[#%x,INIT_2:]]                    <_init_2>
+# CHECK: callq 0x[[#%x,INIT_2:]]                    <_init_2>
+# CHECK: callq 0x[[#%x,INIT_3:]]                    <_init_3>
 
 ### TODO:
 ### * Fold: funcs only 
diff er in alignment
@@ -77,291 +96,167 @@ _not_abs:
 #--- main.s
 .subsections_via_symbols
 .text
-.globl _h
-.alt_entry _h
-
-### Fold: _a1 & _a2 have identical bodies, flags, relocs
 
-.globl _a1
-.p2align 2
-_a1:
-  callq _d
-### No fold: _h is an alt entry past _a1
-_h:
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
+_abs1a_ref:
   movabs $_abs1a, %rdx
-  movl $0, %eax
-  ret
-
-.globl _a2
-.p2align 2
-_a2:
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
-  movabs $_abs1a, %rdx
-  movl $0, %eax
-  ret
 
-### Fold: reference to absolute symbol with 
diff erent name but identical value
-
-.globl _a3
-.p2align 2
-_a3:
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
+_abs1b_ref:
   movabs $_abs1b, %rdx
-  movl $0, %eax
-  ret
 
-### No fold: the absolute symbol value 
diff ers
+_abs1a_ref_with_addend:
+  movabs $_abs1a + 3, %rdx
 
-.globl _b
-.p2align 2
-_b:
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
+_abs1b_ref_with_addend:
+  movabs $_abs1b + 3, %rdx
+
+## No fold: the absolute symbol value 
diff ers
+_abs2_ref:
   movabs $_abs2, %rdx
-  movl $0, %eax
-  ret
 
-### No fold: _not_abs has the same value as _abs1{a,b}, but is not absolute.
+## No fold: _not_abs has the same value as _abs1{a,b}, but is not absolute.
+_not_abs_ref:
+  movabs $_not_abs, %rdx
 
-.globl _b2
-.p2align 2
-_b2:
-  callq _d
+_dylib_ref_1:
   mov ___nan at GOTPCREL(%rip), %rax
   callq ___isnan
-  movabs $_not_abs, %rdx
-  movl $0, %eax
-  ret
-
-### No fold: _c has slightly 
diff erent body from _a1 & _a2
 
-.globl _c
-.p2align 2
-_c:
-  callq _d
+_dylib_ref_2:
   mov ___nan at GOTPCREL(%rip), %rax
   callq ___isnan
-  movabs $_abs1a, %rdx
-  movl $1, %eax
-  ret
 
-### No fold: _d has the same body as _a1 & _a2, but _d is recursive!
+## No fold: referent dylib symbol 
diff ers
+_dylib_ref_3:
+  mov ___inf at GOTPCREL(%rip), %rax
+  callq ___inf
+
+## We can merge two sections even if one of them has an alt entry. Just make
+## sure we don't merge the alt entry symbol with a regular symbol.
+.alt_entry _alt
+_with_alt_entry:
+  movq $3132, %rax
+_alt:
+  ret
 
-.globl _d
-.p2align 2
-_d:
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
-  movabs $_abs1a, %rdx
-  movl $0, %eax
+_no_alt_entry:
+  movq $3132, %rax
   ret
 
-### No fold: the function body is longer
+_defined_ref_with_addend_1:
+  callq _with_alt_entry + 4
 
-.globl _e
-.p2align 2
-_e:
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
-  movabs $_abs1a, %rdx
-  movl $0, %eax
-  ret
-  nop
+_defined_ref_with_addend_2:
+  callq _with_alt_entry + 4
 
-### No fold: GOT referent dylib symbol 
diff ers
+## _recursive has the same body as its next two callers, but cannot be folded
+## with them.
+_recursive:
+  callq _recursive
 
-.globl _f
-.p2align 2
-_f:
-  callq _d
-  mov ___inf at GOTPCREL(%rip), %rax
-  callq ___isnan
-  movabs $_abs1a, %rdx
-  movl $0, %eax
-  ret
+_call_recursive_1:
+  callq _recursive
 
-### No fold: call referent dylib symbol 
diff ers
+_call_recursive_2:
+  callq _recursive
 
-.globl _g
-.p2align 2
-_g:
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isinf
-  movabs $_abs1a, %rdx
-  movl $0, %eax
-  ret
+## Functions of 
diff erent lengths should not be folded
+_check_length_1:
+  movq $97, %rax
+
+_check_length_2:
+  movq $97, %rax
+  .space 1
 
-### No fold: functions have personality and/or LSDA
-### Mere presence of personality and/or LSDA isolates a function into its own
-### equivalence class. We don't care if two functions happen to have identical
-### personality & LSDA.
+_my_personality:
+  mov $1345, %rax
 
-.globl _i
-.p2align 2
-_i:
+## No fold: functions have unwind info.
+## FIXME: Fold functions with identical unwind info.
+_has_unwind_1:
   .cfi_startproc
-  .cfi_personality 155, _my_personality0
-  .cfi_lsda 16, _exception0
+  .cfi_personality 155, _my_personality
   .cfi_def_cfa_offset 16
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
-  movabs $_abs1a, %rdx
-  movl $0, %eax
   ret
   .cfi_endproc
 
-.globl _j
-.p2align 2
-_j:
+_has_unwind_2:
   .cfi_startproc
-  .cfi_personality 155, _my_personality0
-  .cfi_lsda 16, _exception0
+  .cfi_personality 155, _my_personality
   .cfi_def_cfa_offset 16
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
-  movabs $_abs1a, %rdx
-  movl $0, %eax
   ret
   .cfi_endproc
 
-### No fold: _k1 is in a 
diff erent section from _a1
-.section __TEXT,__foo
-.globl _k1
-.p2align 2
-_k1:
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
-  movabs $_abs1a, %rdx
-  movl $0, %eax
-  ret
-  nopl (%rax)
-
-### Fold: _k2 is in a section that gets renamed and output as __text
-.section __TEXT,__StaticInit
-.globl _k2
-.p2align 2
-_k2:
-  callq _d
-  mov ___nan at GOTPCREL(%rip), %rax
-  callq ___isnan
-  movabs $_abs1a, %rdx
-  movl $0, %eax
-  ret
-## For some reason, llvm-mc generates 
diff erent nop encodings when adding
-## padding for __StaticInit vs __text functions. So we explicitly specify the
-## nop here to make sure this function can be folded with _a1.
-  nopl (%rax)
-
-### Fold: Simple recursion
-
-.text
-.globl _sr1
-.p2align 2
-_sr1:
-  callq _sr1
-  movl $0, %eax
-  ret
-
-.globl _sr2
-.p2align 2
-_sr2:
-  callq _sr2
-  movl $0, %eax
-  ret
-
-### Fold: Mutually-recursive functions with symmetric bodies
-
-.globl _mr1
-.p2align 2
-_mr1:
-  callq _mr1 # call myself
-  callq _mr2 # call my twin
-  movl $0, %eax
-  ret
-
-.globl _mr2
-.p2align 2
-_mr2:
-  callq _mr2 # call myself
-  callq _mr1 # call my twin
-  movl $0, %eax
-  ret
-
-### Fold: Mutually-recursive functions with identical bodies
-###
-### FIXME: This test is currently broken. Recursive call sites have no relocs
-### and the non-zero displacement field is already written to the section
-### data, while non-recursive call sites use symbol relocs and section data
-### contains zeros in the displacement field. Thus, ICF's equalsConstant()
-### finds that the section data doesn't match.
-###
-### ELF folds this case properly because it emits symbol relocs for all calls,
-### even recursive ones.
-
-.globl _xr1
-.p2align 2
-_xr1:
-  callq _xr1 # call myself
-  callq _xr2 # call my twin
+## Fold: Mutually-recursive functions with symmetric bodies
+_mutually_recursive_1:
+  callq _mutually_recursive_1 # call myself
+  callq _mutually_recursive_2 # call my twin
+
+_mutually_recursive_2:
+  callq _mutually_recursive_2 # call myself
+  callq _mutually_recursive_1 # call my twin
+
+## Fold: Mutually-recursive functions with identical bodies
+##
+## FIXME: This test is currently broken. Recursive call sites have no relocs
+## and the non-zero displacement field is already written to the section
+## data, while non-recursive call sites use symbol relocs and section data
+## contains zeros in the displacement field. Thus, ICF's equalsConstant()
+## finds that the section data doesn't match.
+##
+## ELF folds this case properly because it emits symbol relocs for all calls,
+## even recursive ones.
+
+_asymmetric_recursive_1:
+  callq _asymmetric_recursive_1 # call myself
+  callq _asymmetric_recursive_2 # call my twin
   movl $3, %eax
-  ret
 
-.globl _xr2
-.p2align 2
-_xr2:
-  callq _xr1 # call my twin
-  callq _xr2 # call myself
+_asymmetric_recursive_2:
+  callq _asymmetric_recursive_1 # call my twin
+  callq _asymmetric_recursive_2 # call myself
   movl $3, %eax
-  ret
 
-###
+_init_1:
+  movq $12938, %rax
 
-.globl _main
-.p2align 2
-_main:
-  callq _a1
-  callq _a2
-  callq _a3
-  callq _b
-  callq _b2
-  callq _c
-  callq _d
-  callq _e
-  callq _f
-  callq _g
-  callq _h
-  callq _i
-  callq _j
-  callq _k1
-  callq _k2
-  callq _sr1
-  callq _sr2
-  callq _mr1
-  callq _mr2
-  callq _xr1
-  callq _xr2
-  ret
+## Fold: _init_2 is in a section that gets renamed and output as __text
+.section __TEXT,__StaticInit
+_init_2:
+  movq $12938, %rax
 
-.globl _my_personality0
-.p2align 2
-_my_personality0:
-  movl $0, %eax
-  ret
+## No fold: _init_3 is in a 
diff erent output section from _init_{1,2}
+.section __TEXT,__foo
+_init_3:
+  movq $12938, %rax
 
-.section __TEXT,__gcc_except_tab
-.globl _exception0
-_exception0:
-  .space 1
+.text
+.globl _main
+_main:
+  callq _abs1a_ref
+  callq _abs1b_ref
+  callq _abs1a_ref_with_addend
+  callq _abs1b_ref_with_addend
+  callq _abs2_ref
+  callq _not_abs_ref
+  callq _dylib_ref_1
+  callq _dylib_ref_2
+  callq _dylib_ref_3
+  callq _alt
+  callq _with_alt_entry
+  callq _no_alt_entry
+  callq _defined_ref_with_addend_1
+  callq _defined_ref_with_addend_2
+  callq _recursive
+  callq _call_recursive_1
+  callq _call_recursive_2
+  callq _check_length_1
+  callq _check_length_2
+  callq _has_unwind_1
+  callq _has_unwind_2
+  callq _mutually_recursive_1
+  callq _mutually_recursive_2
+  callq _asymmetric_recursive_1
+  callq _asymmetric_recursive_2
+  callq _init_1
+  callq _init_2
+  callq _init_3


        


More information about the llvm-commits mailing list