This is an archive of the discontinued LLVM Phabricator instance.

[ThinLTO] Always import constants
ClosedPublic

Authored by evgeny777 on Nov 18 2019, 9:33 AM.

Details

Summary

Since D69561 we started to import readonly vars with non-trivial initializers. However this isn't always the case with compile time constants, because thin LTO analysis pass is not always detecting them as readonly. Such thing happens in two cases:

  • constant object is referenced in initializer of some other object
  • constant object is referenced by instruction which is not non-volatile load.

This patch forces read-only attribute for constants, regardless of their usage

Diff Detail

Event Timeline

evgeny777 created this revision.Nov 18 2019, 9:33 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 18 2019, 9:33 AM
evgeny777 planned changes to this revision.Nov 19 2019, 7:49 AM

Found a bug, will resubmit after fix and more thorough tests.

evgeny777 updated this revision to Diff 230454.Nov 21 2019, 7:00 AM

I reimplemented the patch, now using extra 'Constant' attribute in GlobalVarSummary.

The goal is to allow importing of constants, which are not being detected as 'ReadOnly'. Such constants are imported with available_externally linkage, still allowing compiler to make some optimizations along the way.

evgeny777 retitled this revision from [ThinLTO] Always treat constant objects as readonly to [ThinLTO] Always import constants.Nov 21 2019, 7:00 AM

Patch was tested on Firefox and LLVM test suites. Both pass flawlessly

I reimplemented the patch, now using extra 'Constant' attribute in GlobalVarSummary.

The goal is to allow importing of constants, which are not being detected as 'ReadOnly'. Such constants are imported with available_externally linkage, still allowing compiler to make some optimizations along the way.

Looks good at first glimpse. Out of curiosity, what problem do you run into when you unify ReadOnly with Constant?

Out of curiosity, what problem do you run into when you unify ReadOnly with Constant?

When constant is always treated as ReadOnly it is also always internalized. Now if constant 'A' references constant 'B' in initializer you also have to import constant 'B' when constant 'A' is imported. Otherwise there is linker undef,
because both A and B are internal. This requires recursive variable import which we currently lack.

The more serious problem however is that if constant is not unnamed_addr you can't internalize it at all, because you may end up with different copies of it, each having unique address. So in any case some extra attribute in
GlobalVarSummary is needed to indicate if we can internalize ReadOnly var or not.

Please update the patch description (still talks about forcing read only).

Presumably new flag should be added to llvm::computeLTOCacheKey where it already hashes the read/write only flags.

Out of curiosity, what problem do you run into when you unify ReadOnly with Constant?

When constant is always treated as ReadOnly it is also always internalized. Now if constant 'A' references constant 'B' in initializer you also have to import constant 'B' when constant 'A' is imported. Otherwise there is linker undef,
because both A and B are internal. This requires recursive variable import which we currently lack.

The more serious problem however is that if constant is not unnamed_addr you can't internalize it at all, because you may end up with different copies of it, each having unique address. So in any case some extra attribute in
GlobalVarSummary is needed to indicate if we can internalize ReadOnly var or not.

I see a test for the case where the constant must be imported as promoted, but perhaps there should be one to ensure we can import as internal when possible?

llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
604

Does the change to the write only initialization affect anything user visible? I was trying to reason through it but haven't convinced myself either way. I.e. will it affect which variables are internalized/zeroinitialized?

722

Should this be an assert rather than an if? Looks like we assume it is a GVar since we create a summary for such below. Not sure if def in inline asm can be an alias, but we certainly seem to assume not here.

llvm/test/ThinLTO/X86/import-constant.ll
2

Looks like it is promoted, not internalized?

16

outer is internalized and given zeroinitializer because it is write only I assume - can you add a comment to that effect here?

17

Check that also promoted in exporting module?

llvm/test/ThinLTO/X86/referenced_by_constant.ll
5–6

Looks like this comment should be updated now?

evgeny777 updated this revision to Diff 233615.Dec 12 2019, 7:36 AM
evgeny777 marked 2 inline comments as done.
  • Added test case for 'readonly' constants (import-ro-constant.ll)
  • Added support for 'Constant' attribute to dot dumper
  • Addressed other comments
llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
604

I thought it made sense, because no variable can be both constant and writeonly. However setting it to false doesn't really change anything so I removed this.

722

Yep. It can be just cast<GlobalVariable> instead

Sorry for the delay, I lost track of this one.

llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
604

Ok, true. I'm not sure why I was concerned - I'm ok with the earlier version of the code, agree that it doesn't really make sense to start out with marking it possibly WriteOnly if it cannot be.

llvm/test/ThinLTO/X86/import-constant.ll
2

Looking at this test again, I guess @_ZL3Obj must be getting internalized after promotion, which is why it gets optimized away in the OPT version. Could you check it directly after the internalization phase? I also had a couple other suggestions below.

ormris added a subscriber: ormris.Jan 13 2020, 11:45 AM
evgeny777 marked an inline comment as done.Jan 14 2020, 5:59 AM
evgeny777 added inline comments.
llvm/test/ThinLTO/X86/import-constant.ll
2

Looking at this test again, I guess @_ZL3Obj must be getting internalized after promotion, which is why it gets optimized away in the OPT version.

It's been promoted, not internalized. However @_ZL3Obj is constant so it can be folded even when it has available_externally linkage

evgeny777 updated this revision to Diff 237968.Jan 14 2020, 6:44 AM

Addressed review comments

Can you re-upload the latest with context? It isn't available and therefore I can't compare the last two diffs.

evgeny777 updated this revision to Diff 238004.Jan 14 2020, 9:22 AM

Ah, sorry, uploaded wrong file.

This revision is now accepted and ready to land.Jan 14 2020, 9:29 AM
This revision was automatically updated to reflect the committed changes.