[lld] r318071 - Disable GC and ICF when /debug is present

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 13 10:38:25 PST 2017


Author: rnk
Date: Mon Nov 13 10:38:25 2017
New Revision: 318071

URL: http://llvm.org/viewvc/llvm-project?rev=318071&view=rev
Log:
Disable GC and ICF when /debug is present

ICF and GC impair debugging, so MSVC disables these optimizations when
/debug is passed. They are still on by default when no PDB is produced.

This change also makes /opt:ref enable ICF, which is consistent with
MSVC: https://msdn.microsoft.com/en-us/library/bxwfs976.aspx

We should consider making /opt:icf fold readonly data in the near
future. LLD used to do this, but we disabled it because it breaks too
many programs. MSVC only does this if the user explicitly passes
/opt:icf.

Reviewers: ruiu, pcc

Subscribers: llvm-commits

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

Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/test/COFF/icf-associative.test
    lld/trunk/test/COFF/icf-simple.test
    lld/trunk/test/COFF/pdb-global-gc.yaml
    lld/trunk/test/COFF/pdb-import-gc.yaml

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=318071&r1=318070&r2=318071&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Mon Nov 13 10:38:25 2017
@@ -896,50 +896,51 @@ void LinkerDriver::link(ArrayRef<const c
   if (auto *Arg = Args.getLastArg(OPT_implib))
     Config->Implib = Arg->getValue();
 
-  // Handle /opt
+  // Handle /opt.
+  bool DoGC = !Args.hasArg(OPT_debug);
+  unsigned ICFLevel = 1; // 0: off, 1: limited, 2: on
   for (auto *Arg : Args.filtered(OPT_opt)) {
     std::string Str = StringRef(Arg->getValue()).lower();
     SmallVector<StringRef, 1> Vec;
     StringRef(Str).split(Vec, ',');
     for (StringRef S : Vec) {
-      if (S == "noref") {
-        Config->DoGC = false;
-        Config->DoICF = false;
-        continue;
-      }
-      if (S == "icf" || S.startswith("icf=")) {
-        Config->DoICF = true;
-        continue;
-      }
-      if (S == "noicf") {
-        Config->DoICF = false;
-        continue;
-      }
-      if (S.startswith("lldlto=")) {
+      if (S == "ref") {
+        DoGC = true;
+      } else if (S == "noref") {
+        DoGC = false;
+      } else if (S == "icf" || S.startswith("icf=")) {
+        ICFLevel = 2;
+      } else if (S == "noicf") {
+        ICFLevel = 0;
+      } else if (S.startswith("lldlto=")) {
         StringRef OptLevel = S.substr(7);
         if (OptLevel.getAsInteger(10, Config->LTOOptLevel) ||
             Config->LTOOptLevel > 3)
           error("/opt:lldlto: invalid optimization level: " + OptLevel);
-        continue;
-      }
-      if (S.startswith("lldltojobs=")) {
+      } else if (S.startswith("lldltojobs=")) {
         StringRef Jobs = S.substr(11);
         if (Jobs.getAsInteger(10, Config->LTOJobs) || Config->LTOJobs == 0)
           error("/opt:lldltojobs: invalid job count: " + Jobs);
-        continue;
-      }
-      if (S.startswith("lldltopartitions=")) {
+      } else if (S.startswith("lldltopartitions=")) {
         StringRef N = S.substr(17);
         if (N.getAsInteger(10, Config->LTOPartitions) ||
             Config->LTOPartitions == 0)
           error("/opt:lldltopartitions: invalid partition count: " + N);
-        continue;
-      }
-      if (S != "ref" && S != "lbr" && S != "nolbr")
+      } else if (S != "lbr" && S != "nolbr")
         error("/opt: unknown option: " + S);
     }
   }
 
+  // Limited ICF is enabled if GC is enabled and ICF was never mentioned
+  // explicitly.
+  // FIXME: LLD only implements "limited" ICF, i.e. it only merges identical
+  // code. If the user passes /OPT:ICF explicitly, LLD should merge identical
+  // comdat readonly data.
+  if (ICFLevel == 1 && !DoGC)
+    ICFLevel = 0;
+  Config->DoGC = DoGC;
+  Config->DoICF = ICFLevel > 0;
+
   // Handle /lldsavetemps
   if (Args.hasArg(OPT_lldsavetemps))
     Config->SaveTemps = true;

Modified: lld/trunk/test/COFF/icf-associative.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/icf-associative.test?rev=318071&r1=318070&r2=318071&view=diff
==============================================================================
--- lld/trunk/test/COFF/icf-associative.test (original)
+++ lld/trunk/test/COFF/icf-associative.test Mon Nov 13 10:38:25 2017
@@ -1,5 +1,5 @@
 # RUN: yaml2obj < %s > %t.obj
-# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \
+# RUN: lld-link /opt:icf /entry:foo /out:%t.exe /subsystem:console /include:bar \
 # RUN:   /debug /verbose %t.obj > %t.log 2>&1
 # RUN: FileCheck %s < %t.log
 

Modified: lld/trunk/test/COFF/icf-simple.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/icf-simple.test?rev=318071&r1=318070&r2=318071&view=diff
==============================================================================
--- lld/trunk/test/COFF/icf-simple.test (original)
+++ lld/trunk/test/COFF/icf-simple.test Mon Nov 13 10:38:25 2017
@@ -1,5 +1,5 @@
 # RUN: yaml2obj < %s > %t.obj
-# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \
+# RUN: lld-link /opt:icf /entry:foo /out:%t.exe /subsystem:console /include:bar \
 # RUN:   /verbose %t.obj > %t.log 2>&1
 # RUN: FileCheck -check-prefix=ICF %s < %t.log
 
@@ -13,6 +13,31 @@
 # RUN:   /verbose /opt:noref,noicf %t.obj > %t.log 2>&1
 # RUN: FileCheck -check-prefix=NOICF %s < %t.log
 
+# ICF is on by default (no /opt: flags).
+# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console \
+# RUN:   /include:bar /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=ICF %s < %t.log
+
+# /debug disables ICF.
+# RUN: lld-link /debug /entry:foo /out:%t.exe /subsystem:console \
+# RUN:   /include:bar /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=NOICF %s < %t.log
+
+# /opt:noref disables ICF.
+# RUN: lld-link /opt:noref /entry:foo /out:%t.exe /subsystem:console \
+# RUN:   /include:bar /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=NOICF %s < %t.log
+
+# /debug /opt:ref enables ICF.
+# RUN: lld-link /debug /opt:ref /entry:foo /out:%t.exe /subsystem:console \
+# RUN:   /include:bar /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=ICF %s < %t.log
+
+# /debug /opt:noicf,ref disables ICF.
+# RUN: lld-link /debug /opt:noicf,ref /entry:foo /out:%t.exe /subsystem:console \
+# RUN:   /include:bar /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=NOICF %s < %t.log
+
 # NOICF-NOT: Removed foo
 # NOICF-NOT: Removed bar
 

Modified: lld/trunk/test/COFF/pdb-global-gc.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/pdb-global-gc.yaml?rev=318071&r1=318070&r2=318071&view=diff
==============================================================================
--- lld/trunk/test/COFF/pdb-global-gc.yaml (original)
+++ lld/trunk/test/COFF/pdb-global-gc.yaml Mon Nov 13 10:38:25 2017
@@ -1,7 +1,7 @@
 # RUN: yaml2obj %s -o %t.obj
 # RUN: llvm-mc %S/Inputs/pdb-global-gc.s -triple x86_64-windows-msvc -filetype=obj -o %t2.obj
 # RUN: lld-link %t.obj %t2.obj -debug -entry:main \
-# RUN:          -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb -verbose
+# RUN:          -nodefaultlib -opt:ref -out:%t.exe -pdb:%t.pdb -verbose
 # RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s
 
 # This tests the case where an __imp_ chunk is discarded by linker GC. The debug

Modified: lld/trunk/test/COFF/pdb-import-gc.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/pdb-import-gc.yaml?rev=318071&r1=318070&r2=318071&view=diff
==============================================================================
--- lld/trunk/test/COFF/pdb-import-gc.yaml (original)
+++ lld/trunk/test/COFF/pdb-import-gc.yaml Mon Nov 13 10:38:25 2017
@@ -1,6 +1,6 @@
 # RUN: yaml2obj %s -o %t.obj
 # RUN: lld-link %t.obj %S/Inputs/pdb-import-gc.lib -debug -entry:main \
-# RUN:          -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb
+# RUN:          -nodefaultlib -opt:ref -out:%t.exe -pdb:%t.pdb
 # RUN: llvm-pdbutil dump -globals -symbols %t.pdb | FileCheck %s
 
 # This tests the case where an __imp_ chunk is discarded by linker GC. The debug




More information about the llvm-commits mailing list