forked from OSchip/llvm-project
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 llvm-svn: 318071
This commit is contained in:
parent
a9e47fd7d9
commit
c2dcdd852b
|
@ -896,50 +896,51 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
|||
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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue