This is an archive of the discontinued LLVM Phabricator instance.

[clang] A Unified LTO Bitcode Frontend
ClosedPublic

Authored by ormris on Apr 14 2022, 9:41 AM.

Details

Summary

The unified LTO pipeline creates a single LTO bitcode structure that can be
used by Thin or Full LTO. This means that LKTO mode can be chosen at link
time and that all LTO bitcode produced by the pipeline is compatible, from
an optimization perspective. This makes the behavior of LTO a bit more
predictable by normalizing the set of LTO features supported by each LTO
bitcode file.

Example usage:

clang -flto -funified-lto foo.c
clang -flto -funified-lto bar.c

ld.lld --lto=full foo.o bar.o -o baz.elf

The RFC discussing the details and rational for this change is here:
https://discourse.llvm.org/t/rfc-a-unified-lto-bitcode-frontend/61774

Diff Detail

Event Timeline

ormris created this revision.Apr 14 2022, 9:41 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 14 2022, 9:41 AM
ormris requested review of this revision.Apr 14 2022, 9:41 AM
ormris edited the summary of this revision. (Show Details)Apr 14 2022, 9:48 AM
ormris edited the summary of this revision. (Show Details)Apr 14 2022, 10:17 AM
ormris edited the summary of this revision. (Show Details)

As mentioned on the RFC thread a little bit ago, I think the split LTO handling should be separated from the unified LTO pipeline. So some of these comments may be moot if that is done.

clang/lib/CodeGen/BackendUtil.cpp
950

I think this ?: logic is all equivalent to simply setting the flag to !CodeGenOpts.UnifiedLTO. While as noted elsewhere I'd like to separate the split LTO unit handling from the unified LTO pipeline model, I'm not sure I understand why you would want to set this module flag to false when CodeGenOpts.UnifiedLTO==true under the current patch intent.

clang/lib/Driver/ToolChains/Clang.cpp
4695

Why the PS4 special handling? Also, shouldn't LTO unit be enabled in unified LTO mode?

7048

I'd like to separate the split LTO unit setting from Unified LTO as I think they are orthogonal.

clang/lib/Frontend/CompilerInvocation.cpp
1743

Opts.PrepareForLTO was set to false a couple lines up, so I don't think this if condition will ever evaluate to true?

1758

Why is the default being set differently for PS4?

ormris updated this revision to Diff 423495.Apr 18 2022, 5:25 PM
ormris retitled this revision from [WIP][clang] A Unified LTO Bitcode Frontend to [WIP][clang][lld] A Unified LTO Bitcode Frontend.Apr 18 2022, 5:25 PM
ormris edited the summary of this revision. (Show Details)

Add LLD driver changes to this patch. Disable split LTO units by default. As discussed here: https://discourse.llvm.org/t/rfc-a-unified-lto-bitcode-frontend/61774/15

ormris updated this revision to Diff 523204.May 17 2023, 3:56 PM

Changelog:

  • Rebased
Herald added a project: Restricted Project. · View Herald TranscriptMay 17 2023, 3:56 PM
ormris updated this revision to Diff 523483.May 18 2023, 11:46 AM

Remove duplicated LLVM tests.

ormris updated this revision to Diff 523813.May 19 2023, 9:09 AM

Attempt to fix premerge checks

ormris updated this revision to Diff 526178.May 26 2023, 1:16 PM

clang-format

ormris updated this revision to Diff 527696.Jun 1 2023, 6:20 PM

Use the ThinLTO pre-link pipeline as the Unified LTO pre-link pipeline, as discussed in the RFC.

gentle ping

The lld side has no test. I think we normally create separate patches for clang and lld. So you may want to reuse D123805 for lld changes.
See lld/test/ELF/lto/ for tests.

MaskRay added inline comments.Jul 5 2023, 11:23 PM
clang/lib/CodeGen/BackendUtil.cpp
898–900

Simplify this with if (IsThinLTO || (IsLTO && CodeGenOpts.UnifiedLTO))

clang/lib/Driver/ToolChains/Clang.cpp
4554

Search for Args.addOptInFlag

4695

Do you want to use isPS() special case both PS4 and PS5? Or is it that just PS4 is special?

Is only PS4 is special, the summary should mention why.

7028–7029

Add a comment why PS4 is special.

clang/test/CodeGen/asan-unified-lto.ll
9

Consider checking a few more things including the module flag metadata beside the global variable name.

16

ptr. Avoid obsoleted typed pointers.

clang/test/CodeGen/emit-summary-index.c
17

Add a comment with /// (for non-RUN non-CHECK lines) about the purpose of the two RUN lines.

clang/test/CodeGen/unified-lto-pipeline.c
2

Without --target, this uses the default target triple which may fail for some exotic platforms.

Prefer %clang_cc1 for non-driver tests. Instead of comparing the output files, test -fdebug-pass-manager output.

MaskRay added inline comments.Jul 5 2023, 11:25 PM
clang/test/Driver/unified-whole-program-vtables.c
2

I think it'll be more readable if you place all -funitied-lto related driver tests in one file, instead of spreading them into unified-whole-program-vtables.c and lto-unit.c

Use --target= for new tests. -target has been deprecated since Clang 3.4

MaskRay added 1 blocking reviewer(s): MaskRay.Jul 5 2023, 11:26 PM
ormris added inline comments.Jul 10 2023, 11:05 AM
clang/lib/CodeGen/BackendUtil.cpp
898–900

Fixed

950

That's a good point. I've removed this change.

clang/lib/Driver/ToolChains/Clang.cpp
4554

There's driver code that depend on the value of this flag, so I do need to store it. Args.addOptInFlag doesn't return the value of the flag. Is there an advantage to calling addOptInFlag, then hasFlag?

4695

Fixed.

7028–7029

Fixed.

7048

Fixed

clang/test/CodeGen/asan-unified-lto.ll
16

Fixed

clang/test/CodeGen/emit-summary-index.c
17

Fixed

clang/test/CodeGen/unified-lto-pipeline.c
2

Why test the pipeline rather than binary equivalence? Identical bitcode files is a key part of this feature.

clang/test/Driver/unified-whole-program-vtables.c
2

Agreed. Fixed.

ormris updated this revision to Diff 538740.Jul 10 2023, 11:07 AM

@MaskRay There are very few LLD changes in this review, but we can split this out if it would be more convenient.

@MaskRay There are very few LLD changes in this review, but we can split this out if it would be more convenient.

Yeah, preferably split. I use this convention for most features.

ormris updated this revision to Diff 538803.Jul 10 2023, 1:34 PM

Remove LLD changes from this patch. They're now in D123805.

MaskRay added a comment.EditedJul 11 2023, 12:14 AM

Thank you for the update.

IIUC -flto=full -funified-lto, -flto -funified-lto, and -flto=thin -funified-lto are identical.
-flto=full -funified-lto may be confusing as we treat it as it -flto=thin and use buildThinLTOPreLinkDefaultPipeline.

In the absence of -flto, -funified-lto seems a no-op (I do not see a test).

I wonder whether we should change -funified-lto to become -flto=unified instead.
(For the lld option, I guess --lto-mode={thin,full} may be clearer than --lto={thin,full}, but I don't have a strong opinion... )

clang/lib/Frontend/CompilerInvocation.cpp
1755

hasArg if you don't use A

clang/test/Driver/lto-unit.c
11

Is NOUNIT unused?

clang/test/Driver/unified-lto.c
5 ↗(On Diff #538803)

Is NOUNIT-NOT used?

9 ↗(On Diff #538803)

This test may be better placed in whole-program-vtables.c where this diagnostic is tested.

[WIP][clang][lld] A Unified LTO Bitcode Frontend

You may change the titles of this patch and the lld one... I guess it is named WIP so I ignored reading it for a long time (sorry!).

ormris retitled this revision from [WIP][clang][lld] A Unified LTO Bitcode Frontend to [clang] A Unified LTO Bitcode Frontend.Jul 11 2023, 9:34 AM

IIUC -flto=full -funified-lto, -flto -funified-lto, and -flto=thin -funified-lto are identical.

They're not completely identical. They change the flag passed to the linker when the linker is invoked by the compiler. I think it's worth preserving that workflow. It's used fairly often for manually compiling a project (e.g. clang -flto=thin -funified-lto hello.cpp), but also by CMake.

In the absence of -flto, -funified-lto seems a no-op (I do not see a test).

Good point. Fixed.

For the lld option, I guess --lto-mode={thin,full}

Maybe.... I was trying to mirror -flto and reduce the amount of typing required.

clang/lib/Frontend/CompilerInvocation.cpp
1755

Fixed.

clang/test/Driver/lto-unit.c
11

Fixed.

clang/test/Driver/unified-lto.c
5 ↗(On Diff #538803)

No, but it should be. Fixed.

9 ↗(On Diff #538803)

Fixed

ormris updated this revision to Diff 539198.Jul 11 2023, 10:57 AM

Address comments

IIUC -flto=full -funified-lto, -flto -funified-lto, and -flto=thin -funified-lto are identical.

They're not completely identical. They change the flag passed to the linker when the linker is invoked by the compiler. I think it's worth preserving that workflow. It's used fairly often for manually compiling a project (e.g. clang -flto=thin -funified-lto hello.cpp), but also by CMake.

OK, sounds good. I think the description can be updated to include some examples.
The discourse link has quite a lot of discussions and the commit message/summary can be a good place to summarize all the information.
If I were a newcomer, I would find the discourse link too daunting to comprehend...

In the absence of -flto, -funified-lto seems a no-op (I do not see a test).

Good point. Fixed.

For the lld option, I guess --lto-mode={thin,full}

Maybe.... I was trying to mirror -flto and reduce the amount of typing required.

clang/test/CodeGen/unified-lto-pipeline.c
2

cmp %t.0 %t.1 should be retained. My point is that we probably should test some output to demonstrate that his is a ThinLTO pipeline.

// RUN: not cmp %t.2 %t.3 is probably less useful if we can demonstrate that the pipeline is different.

ormris edited the summary of this revision. (Show Details)Jul 11 2023, 11:55 AM
ormris added inline comments.Jul 11 2023, 1:12 PM
clang/test/CodeGen/unified-lto-pipeline.c
2

Ah that makes sense. Fixed.

ormris updated this revision to Diff 539259.Jul 11 2023, 1:14 PM

Address comments. I've updated the review description as well.

MaskRay added a comment.EditedJul 11 2023, 1:16 PM

Sorry for extra nitpicking:)

[clang] A Unified LTO Bitcode Frontend

I think we typically start with a verb and don't capitalize every words, e.g. [clang] Support Unified LTO Bitcode frontend

This means that LKTO mode can be chosen at link [...]

typo: LKTO?

Feel free to incorporate the following to your summary:

# Compile and link. Select regular LTO at link time.
clang -flto -funified-lto -fuse-ld=lld foo.c

# Compile and link. Select ThinLTO at link time.
clang -flto=thin -funified-lto -fuse-ld=lld foo.c

# Link separately, using ThinLTO.
clang -c -flto -funified-lto foo.c  # -flto={full,thin} are identical in terms of compilation actions
clang -flto=thin -fuse-ld=lld foo.o  # pass --lto=thin to ld.lld

# Link separately, using regular LTO.
clang -c -flto -funified-lto foo.c
clang -flto -fuse-ld=lld foo.o  # pass --lto=full to ld.lld
clang/lib/Driver/ToolChains/Clang.cpp
4554

One blank line is sufficient.

MaskRay accepted this revision.Jul 11 2023, 1:23 PM
MaskRay added inline comments.
clang/test/CodeGenCXX/unified-cfi-lto.cpp
5

Did you forget FileCheck?

clang/test/Driver/unified-lto.c
10 ↗(On Diff #539259)

If the path of %s contains -funified-lto, the NOT pattern will fail spuriously. -funified-lto may be unique enough to not cause an issue in practice, but other options did cause an issue IIRC. The conventional solution is to use a double quote to make it really unique enough.
In addition, we typically start with "-cc1" to indicate that we are testing cc1 command line.

// NOUNILTO:     "-cc1"
// NOUNILTO-NOT: "-funified-lto
clang/test/Driver/whole-program-vtables.c
9 ↗(On Diff #539259)

Add a comment /// -funified-lto does not imply -flto, so we still get an error that fwhole-program-vtables has no effect without -flto

This revision is now accepted and ready to land.Jul 11 2023, 1:23 PM
pcc added a comment.Jul 12 2023, 11:59 AM

Looks like this caused some buildbot failures, e.g.

https://lab.llvm.org/buildbot/#/builders/168/builds/14547

Can you please take a look?

Yes, looking now.

@pcc I'll remove the failing test while I work on a reproducing this.