Skip to content

SIL: let SingleValueInstruction only inherit from a single SILNode. #35554

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

Merged

Conversation

eeckstein
Copy link
Contributor

@eeckstein eeckstein commented Jan 22, 2021

I had a feature in mind which would have increased our instruction size. To not feel so bad about it, I tried to reduce the instruction size on another end. So I came up with this change. At the end I decided to not implement the feature, but I thought this change is a good thing, anyway.

Letting SingleValueInstruction only inherit from a single SILNode removes the ambiguity when casting from a SingleValueInstruction to SILNode, which makes the code simpler. E.g. the "isRepresentativeSILNode" logic is not needed anymore.
Also, it reduces the size of the most used instruction class - SingleValueInstruction - by one word.

Conceptually, SILInstruction is still a SILNode. But implementation-wise SILNode is not a base class of SILInstruction anymore.
Only the two sub-classes of SILInstruction - SingleValueInstruction and NonSingleValueInstruction - inherit from SILNode. SingleValueInstruction's SILNode is embedded into a ValueBase and its relative offset in the class is the same as in NonSingleValueInstruction (see SILNodeOffsetChecker).
This makes it possible to cast from a SILInstruction to a SILNode without knowing which SILInstruction sub-class it is.
Casting to SILNode cannot be done implicitly, but only with an LLVM cast or with SILInstruction::asSILNode(). But this is a rare case anyway.

Only the last commit of this PR does the actual SILNode change. All previous commits contain small cleanups, which are required for the change, but are good for their own.

@eeckstein eeckstein requested review from atrick and rjmccall January 22, 2021 13:21
@eeckstein
Copy link
Contributor Author

@swift-ci test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 5220ca24b23624cf5394664bedde0b0be94f72b8

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

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

Looks great! I'm happy to see the representative node stuff go away. And I think SILNode should be an implementation detail whose type isn't used outside the implementation of SILValue/Instruction.

What's the size of SingleValueInstruction now?

Loosely related commentary:

I would not want to add "dirty" bits to SILInstruction because it's generally bad design to cache analysis results in the IR, and you could reap the same benefits just by maintaining a unique ID or even an ordering. That lets you easily manage dense data structures that contain analysis results and can be useful for fast checks on relative instruction order. It's a lot harder to manage with instructions vs. blocks though. For ordering, you would want to leave holes in the numbering, and even with unordered IDs it'll end up with plenty of holes. That degrades the performance of data structures and get into a nasty game of heuristics.

Replace the `isa(SILNode *)` with `isa(SILInstruction *)` and `isa(SILValue)`.
This is much clearer and it also works if the SILValue is a MultiValueInstructionResult of an apply instruction.

Also, use `isa` instead of `classof` in canOptimize()
Split `markValueLive(SILNode *)` into `markValueLive(SILValue)` and `markInstructionLive(SILInstruction*)`
… when checking for invariant arguments.

Use `getDefiningInstruction` instead of casting a a SILValue to SingleValueInstruction.
…om SILNode* to SILValue

A small cleanup, NFC.
This resolves a FIXME.
Also, use `getDefiningInstruction()` instead of `getRepresentativeSILNodeInObject()`

NFC
This removes the ambiguity when casting from a SingleValueInstruction to SILNode, which makes the code simpler. E.g. the "isRepresentativeSILNode" logic is not needed anymore.
Also, it reduces the size of the most used instruction class - SingleValueInstruction - by one pointer.

Conceptually, SILInstruction is still a SILNode. But implementation-wise SILNode is not a base class of SILInstruction anymore.
Only the two sub-classes of SILInstruction - SingleValueInstruction and NonSingleValueInstruction - inherit from SILNode. SingleValueInstruction's SILNode is embedded into a ValueBase and its relative offset in the class is the same as in NonSingleValueInstruction (see SILNodeOffsetChecker).
This makes it possible to cast from a SILInstruction to a SILNode without knowing which SILInstruction sub-class it is.
Casting to SILNode cannot be done implicitly, but only with an LLVM `cast` or with SILInstruction::asSILNode(). But this is a rare case anyway.
@eeckstein eeckstein force-pushed the single-silnode-in-singlevalueinstruction branch from 5220ca2 to ff19917 Compare January 25, 2021 08:56
@eeckstein
Copy link
Contributor Author

@swift-ci smoke test

@eeckstein
Copy link
Contributor Author

@atrick the size of SingleValueInstruction is still 10 words (2 for the inst-list node, 1 for the parent, 3 for ValueBase and 4 for the debug location). Though, I believe we could get the debug location down to 3 words, or even less.

@eeckstein eeckstein merged commit f205b20 into swiftlang:main Jan 25, 2021
@eeckstein eeckstein deleted the single-silnode-in-singlevalueinstruction branch January 25, 2021 11:30
@atrick
Copy link
Contributor

atrick commented Jan 25, 2021

@eeckstein oh well, ideally the debug location would be encoded in one word and the first operand could reside in the same cache line.

return ApplySite();

auto kind = ApplySiteKind::fromNodeKind(i->getKind());
static ApplySite isa(SILInstruction *inst) {
Copy link
Contributor

Choose a reason for hiding this comment

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

@eeckstein I wish you had also renamed this to cast or get. It is weird that this is isa since it doesn't return a bool.

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.

4 participants