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

[RISCV][LLD] Add RISCV zcmt optimise in linker relaxation #77884

Open
wants to merge 54 commits into
base: main
Choose a base branch
from

Conversation

Xinlong-Wu
Copy link
Contributor

This patch is moved from https://reviews.llvm.org/D134600 .
Considering that the LLVM's Phabricator instance has been replaced by a static archive, it is not workable to review on Phabricator anymore. So I reopened this pr and synchronized the latest changes.
I can't reopen previous pr #68551 because the previous branch has been recreated

This patch implements optimizations for the zcmt extension in lld.

A new TableJumpSectio has been added.

Scans each R_RISCV_CALL/R_RISCV_CALL_PLT relocType in each section before the linker relaxation, recording the name of the symbol.

In finalizeContentsthe recorded symbol names are sorted in descending order by the number of jumps.

Optimise and insert a new cm.jt/cm.jalt during the relax process. in the process, we reused theR_RISCV_JAL relocType

co-author: @ScottEgerton

@Xinlong-Wu
Copy link
Contributor Author

I tried linking several common applications and libraries using this patch to compare Zcmt's contribution to reducing Code Szie.

The results can be found in the Sheet or in the image below.

image

Besides that, I found a problem that needs to be discussed.

In TableJumpSection::finalizeContents(), the linker will abort the tbljal optimization and empty the Jump table if tbljal optimization would cause a negative optimization (i.e., the size reduction caused by the Table jump Inst is less than the size increase caused by making the Jump Table).

However, the linker still adds the symbol __jvt_base$ to .symtab . This results in a small increase in program size.

Thus, I tried to delay adding the symbol __jvt_base$ at lld/ELF/Writer.cpp and remove the symbol __jvt_base$ when the Jump Table is not empty. Something like that

But it will crash with error placeholder symbol reached writer at lld/ELF/Symbols.cpp:154. Does anyone can point out anything else should I do to add symbol delay?

Copy link

github-actions bot commented Jan 12, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@MaskRay
Copy link
Member

MaskRay commented Jan 12, 2024

Code size reduction | 0.14% | 0.08% | 0.15% | 0.22% | 0.19% | 0.38%

Let me express my gratitude for the dedicated work you put into measuring the impact. This has been useful to figure out how useful an extension is.

As an established code size reduction feature, global pointer relaxation seems to have a saving larger than this but still needed a lot of discussions whether it was justified (since the numbers aren't great either). The zcmt numbers seem smaller while the implementation is much heavier in assembler/linker and table jump seems to get questions on hardware side whether the little code size saving justifies probably significant performance overhead. I also heard that zcmt is incompatible with another extension. It would be greatly beneficial to see a more substantial commitment from hardware vendors, given the drawbacks, minimal saving, and the considerable implementation complexity.

@asb
Copy link
Contributor

asb commented Jan 16, 2024

The RISC-V code size reduction work-group did some analysis of expected code size improvements from zcmt https://docs.google.com/spreadsheets/d/1bFMyGkuuulBXuIaMsjBINoCWoLwObr1l9h5TAWN8s7k/edit#gid=1679419155 - it would be worth understanding why the results seem so different.

Copy link
Member

@kito-cheng kito-cheng left a comment

Choose a reason for hiding this comment

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

In TableJumpSection::finalizeContents(), the linker will abort the tbljal optimization and empty the Jump table if tbljal optimization would cause a negative optimization (i.e., the size reduction caused by the Table jump Inst is less than the size increase caused by making the Jump Table).

Add a testcase to demonstrate that?

lld/ELF/Options.td Outdated Show resolved Hide resolved
lld/ELF/Arch/RISCV.cpp Show resolved Hide resolved
lld/ELF/Arch/RISCV.cpp Outdated Show resolved Hide resolved
@Xinlong-Wu
Copy link
Contributor Author

I'm trying remove the symble .riscv.jvt when Jump table is empty, But I have noticed .shStrTab has been fixed befor relaxation. I can't remove it from string table. string .riscv.jvt in .shStrTab will always cause a negative effect

lld/ELF/Arch/RISCV.cpp Show resolved Hide resolved
lld/ELF/Arch/RISCV.cpp Outdated Show resolved Hide resolved
// an increase in code size (i.e. the reduction from instruction conversion
// does not cover the code size gain from adding a table entry).
SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
TableJumpSection::finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,

Choose a reason for hiding this comment

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

finalizeEntry seems not modifying any section members and the input EntryMap?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we actually do following 3 things

  1. sort the EntryMap as decrease order by size reduction of each item in EntryMap
  2. drop rest if EntryMap larger then maxSize
  3. drop the item that have a negative effect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants