Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LLD] [MinGW] Hook up --icf=safe to -opt:safeicf #70037

Merged
merged 1 commit into from
Oct 25, 2023

Conversation

mstorsjo
Copy link
Member

Back when the --icf= option was hooked up in the MinGW frontend in LLD, in 2017, lld-link didn't support safe ICF, and mapping it to noicf was suggested in review: https://reviews.llvm.org/D40019

Later in 2021, lld-link did get support for safe ICF in 5bdc5e7 / https://reviews.llvm.org/D97436.

Hook this up for the MinGW frontend as well.

Back when the --icf= option was hooked up in the MinGW frontend
in LLD, in 2017, lld-link didn't support safe ICF, and mapping it
to noicf was suggested in review: https://reviews.llvm.org/D40019?id=122818#inline-349280

Later in 2021, lld-link did get support for safe ICF in
5bdc5e7 / https://reviews.llvm.org/D97436.

Hook this up for the MinGW frontend as well.
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 24, 2023

@llvm/pr-subscribers-lld
@llvm/pr-subscribers-platform-windows

@llvm/pr-subscribers-lld-coff

Author: Martin Storsjö (mstorsjo)

Changes

Back when the --icf= option was hooked up in the MinGW frontend in LLD, in 2017, lld-link didn't support safe ICF, and mapping it to noicf was suggested in review: https://reviews.llvm.org/D40019

Later in 2021, lld-link did get support for safe ICF in 5bdc5e7 / https://reviews.llvm.org/D97436.

Hook this up for the MinGW frontend as well.


Full diff: https://github.com/llvm/llvm-project/pull/70037.diff

2 Files Affected:

  • (modified) lld/MinGW/Driver.cpp (+3-1)
  • (modified) lld/test/MinGW/driver.test (+4-2)
diff --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp
index 8fc9ac54d04a2d1..19bf2d1617057eb 100644
--- a/lld/MinGW/Driver.cpp
+++ b/lld/MinGW/Driver.cpp
@@ -375,7 +375,9 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     StringRef s = a->getValue();
     if (s == "all")
       add("-opt:icf");
-    else if (s == "safe" || s == "none")
+    else if (s == "safe")
+      add("-opt:safeicf");
+    else if (s == "none")
       add("-opt:noicf");
     else
       error("unknown parameter: --icf=" + s);
diff --git a/lld/test/MinGW/driver.test b/lld/test/MinGW/driver.test
index 1fdd494754af4bf..a07c95edb580da1 100644
--- a/lld/test/MinGW/driver.test
+++ b/lld/test/MinGW/driver.test
@@ -205,10 +205,12 @@ GC-SECTIONS: -opt:ref
 RUN: ld.lld -### -m i386pep foo.o 2>&1 | FileCheck -check-prefix ICF-NONE %s
 RUN: ld.lld -### -m i386pep foo.o --icf=none 2>&1 | FileCheck -check-prefix ICF-NONE %s
 RUN: ld.lld -### -m i386pep foo.o -icf=none 2>&1 | FileCheck -check-prefix ICF-NONE %s
-RUN: ld.lld -### -m i386pep foo.o --icf=safe 2>&1 | FileCheck -check-prefix ICF-NONE %s
-RUN: ld.lld -### -m i386pep foo.o -icf=safe 2>&1 | FileCheck -check-prefix ICF-NONE %s
 ICF-NONE: -opt:noicf
 
+RUN: ld.lld -### -m i386pep foo.o --icf=safe 2>&1 | FileCheck -check-prefix ICF-SAFE %s
+RUN: ld.lld -### -m i386pep foo.o -icf=safe 2>&1 | FileCheck -check-prefix ICF-SAFE %s
+ICF-SAFE: -opt:safeicf
+
 RUN: ld.lld -### -m i386pep foo.o --icf=all 2>&1 | FileCheck -check-prefix ICF %s
 RUN: ld.lld -### -m i386pep foo.o -icf=all 2>&1 | FileCheck -check-prefix ICF %s
 RUN: ld.lld -### -m i386pep foo.o --icf all 2>&1 | FileCheck -check-prefix ICF %s

@mstorsjo
Copy link
Member Author

@rnk, back in 2017, https://reviews.llvm.org/D40019?id=122818#inline-349280, you wrote:

I don't think LLD has support for safe ICF. Safe ICF leveraged certain x86_32 ELF relocations that COFF lacks, and failing that, relies on knowledge about the Itanium C++ name mangling rules. LLD doesn't implement anything like that.

As LLD/COFF now does have support for safe ICF since 5bdc5e7, I presume it's safe to use it for the MinGW target as well - as we have the addrsig information encoded in COFF object files these days as well, right? Even if LLD doesn't have any knowledge about the Itanium C++ name mangling (at this level).

@ZequanWu
Copy link
Contributor

Under safe ICF, it currently only checks Microsoft mangled vtable name. You may also want to update that as well to keep the behaviour consistent.

// So are vtables.
if (c->sym && c->sym->getName().starts_with("??_7"))
return true;

Copy link
Collaborator

@rnk rnk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

The 2017 comments predate the addrsig tracking mechanisms that @pcc implemented, so this change makes sense today.

@mstorsjo mstorsjo merged commit 6d66440 into llvm:main Oct 25, 2023
6 checks passed
@mstorsjo mstorsjo deleted the lld-safe-icf branch October 25, 2023 11:38
Andarwinux referenced this pull request in curl/curl-for-win Dec 7, 2023
It tells the compiler to add information to the objects so that the
linker is able to link on a per-symbol basis. Meaning it can leave out
anything that isn't used even when those symbols come from a common
source file. It makes CMake "unity" builds (where the whole library ends
up forming a single source and thus a single object) behave like
non-unity builds. But, it also improves binary sizes linking to a
non-unity libcurl static lib.

The cost is larger static lib sizes.

Also tried enabling this just for curl, but the savings were minimal.

Sizes of Windows binaries (similar effect for Linux):
                                 arm64                 x64                   x86
bin/curl.exe              3632128 -> 3340288    3776512 -> 3164160    3588096 -> 3195392
bin/libcurl*.dll          3400704 -> 3125760    3530240 -> 2957824    3353088 -> 2995712
bin/trurl.exe               35328 ->   40448      40448 ->   34816      34816 ->   34816
lib/libbrotlicommon.a      133042 ->  134386     133174 ->  133944     132324 ->  134298
lib/libbrotlidec.a          45660 ->   56206      48396 ->   55992      47430 ->   53708
lib/libcrypto.a           2631872 -> 3510708    2611626 -> 3496884    2486780 -> 3556980
lib/libcurl.a             1279084 -> 1582434    1162164 -> 1590022    1133396 -> 1708558
lib/libcurl.dll.a           16336 ->   16058      16058 ->   15924      15924 ->   16336
lib/libnghttp2.a           218536 ->  286938     225136 ->  295662     219432 ->  283748
lib/libnghttp3.a           185098 ->  244814     193486 ->  258070     196032 ->  238974
lib/libngtcp2.a            355252 ->  450174     361712 ->  502880     397536 ->  448838
lib/libngtcp2_crypto_*.a    33914 ->   40810      33576 ->   41598      31776 ->   41590
lib/libssh2.a              379836 ->  418346     319888 ->  425182     309564 ->  480336
lib/libssl.a               501996 ->  689596     527972 ->  697640     508858 ->  670440
lib/libz.a                 105672 ->  121990     104406 ->  125238     105358 ->  124510
lib/libzstd.a              662392 ->  887846     826112 ->  869672     796722 ->  726208

not supported on macOS:

https://github.com/curl/curl-for-win/actions/runs/7080192323/job/19267732076#step:3:1491
```
ld: unknown option: --gc-sections
```

https://github.com/curl/curl-for-win/actions/runs/7080192323/job/19267732709#step:3:1494:
```
ld64.lld: error: unknown argument '--gc-sections'
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants