Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Delete fgArgTabEntry::node#24294

Merged
sandreenko merged 7 commits into
dotnet:masterfrom
mikedn:no-call-list
Sep 30, 2019
Merged

Delete fgArgTabEntry::node#24294
sandreenko merged 7 commits into
dotnet:masterfrom
mikedn:no-call-list

Conversation

@mikedn
Copy link
Copy Markdown

@mikedn mikedn commented Apr 28, 2019

This replace the GenTree* fgArgTabEntry::node pointer with a pointer to the late arg (use). This way the node pointer can still be obtained from either fgArgTabEntry::use or fgArgTabEntry::lateUse and we no longer need to special case operand replacement (with the exception of preserving GTF_LATE_ARG).

Contributes to #26307

The extra Use for the this arg does increase memory usage a bit, by around 0.05%. I think it's definitely worth it. And we could recover some of that if we eventually move the this arg to the normal arg list so that GenTreeCall (and all large nodes) becomes one pointer smaller.

No diffs. (crossgen/PMI x86/x64 and altjit arm32/arm64)

@mikedn mikedn force-pushed the no-call-list branch 2 times, most recently from be5e3c7 to f1d4104 Compare April 29, 2019 17:00
@mikedn
Copy link
Copy Markdown
Author

mikedn commented Apr 29, 2019

@CarolEidt

It would be great if we eliminated the need for the fgArgInfo to capture the tree node, though I suspect that's going to be quite a long lead-time task.

Et voila, poof goes fgArgTabEntry::node. Replaced by a pointer to the list node in gtCallLateArgs. Well, it's early stages and it's built on top of other changes (some loop hoisting fix and GT_LIST removal). But anyway, it's doable.

@mikedn mikedn force-pushed the no-call-list branch 3 times, most recently from eb2e4f9 to 09978d3 Compare May 3, 2019 19:53
@mikedn mikedn force-pushed the no-call-list branch 3 times, most recently from e771834 to c727571 Compare May 14, 2019 16:49
@mikedn mikedn changed the title [WIP] Stop using LIST nodes in GenTreeCall [WIP] [Experimental] GenTreeCall refactoring Aug 23, 2019
@mikedn mikedn force-pushed the no-call-list branch 2 times, most recently from 20069b6 to 67a9399 Compare September 21, 2019 15:13
@mikedn mikedn changed the title [WIP] [Experimental] GenTreeCall refactoring [WIP] Delete GenTreeCall::ReplaceCallOperand Sep 21, 2019
@BruceForstall
Copy link
Copy Markdown

cc @sandreenko

@erozenfeld
Copy link
Copy Markdown
Member

@dotnet/jit-contrib

@mikedn mikedn changed the title [WIP] Delete GenTreeCall::ReplaceCallOperand [WIP] Delete fgArgTabEntry::node Sep 26, 2019
@mikedn mikedn changed the title [WIP] Delete fgArgTabEntry::node Delete fgArgTabEntry::node Sep 26, 2019
@mikedn
Copy link
Copy Markdown
Author

mikedn commented Sep 26, 2019

While removing fgArgTabEntry::node I transformed some of the assignments to it into asserts that check that it is indeed updated correctly. Initially I wanted to remove them once CI passes and I run all diffs but I think I'm going to keep these asserts for a while, until more call data structures cleanup is done.

It may seem like the asserts are completly useless since it is obviously impossible for node to not be updated - it simply no longer exists. However, there can be some confusion between late and normal args and at least some of those asserts could help prevent issues arising from this.

Ideally this "late arg" nonsense should just go away. Remains to be seen when I'll get to it, I'm also trying to deal with struct related issues and that seems more useful at the moment. Well, at least until I try to do some struct related work and run into all this nonsense again.

Copy link
Copy Markdown

@sandreenko sandreenko left a comment

Choose a reason for hiding this comment

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

Overal look great, I like how simpler this part looks now.

No diffs. (crossgen/PMI x86/x64 and altjit arm32/arm64)

👍
Do you have PIN data?

Comment thread src/jit/gentree.cpp Outdated
}

if (!Compare(op1->AsCall()->gtCallObjp, op2->AsCall()->gtCallObjp))
if ((op1->AsCall()->gtCallThisArg != nullptr) != (op2->AsCall()->gtCallThisArg != nullptr))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nit: I would create a new block under case GT_CALL: and create locals for op1->gtCall, op1->AsCall()->gtCallThisArg, op2->AsCall()->gtCallThisArg.

Comment thread src/jit/gentree.cpp
Comment thread src/jit/importer.cpp
Comment thread src/jit/morph.cpp Outdated
Comment thread src/jit/morph.cpp Outdated
Comment thread src/jit/compiler.h
GenTree* GetArgNode(unsigned argIndex)
{
return GetArgEntry(argIndex)->node;
return GetArgEntry(argIndex)->GetNode();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

a random thing:
in GenTreeCall::Use::SetNode we check that assert(node != nullptr);, so as I understand our contract is that if we have a Use then we have a not-null node, but we don't check that in the Use constructor, so we can call GenTreeCall::Use(nullptr) and do bad things.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Right, I need to check this. AFAIR I didn't add an assert in the Use constructor due to some funny code in fgArgInfo::fgArgInfo that was manufacturing uses out of thin air. That code is gone now so perhaps I can add an assert.

Comment thread src/jit/lower.cpp
Comment thread src/jit/morph.cpp Outdated
oldArgs = oldArgs->GetNext();
for (unsigned i = 0; i < argTableSize; i++)
{
if (argTable[i]->use == &(*oldUse))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

How much time do we spend in this quadratic loop?

Nit: I do not like &(*oldUse) with hiding castings.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Luckily cloning calls isn't exactly common. The only case I know of is loop hoisiting and that only works with a few "pure" helpers that have 2 arguments.

I don't like &(*oldUse) but I don't understand what do you mean by hiding casts. The only way to avoid this seems to be to avoid using iterators but I'd like to avoid relying on the fact that the arg list is a linked list. It should be an array and using iterators makes changing it easier. Assuming we ever figure out how to deal with the few cases that require as to insert new arguments into this arg list...

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

oldUse's type is UseIterator ,
*oldUse's type is 'Use&' (because of operator overload Use& operator*() const),
'&(*oldUse)'s type is Use*.

with inlining, it looks like &*(oldUse->m_use), maybe we can add Use* UseIterator::GetUse() const and call it here and below?

@mikedn
Copy link
Copy Markdown
Author

mikedn commented Sep 27, 2019

Do you have PIN data?

PIN shows no diff (-/+ 0.01%), that's why I didn't mention it. I suppose one would have expected a small improvement due to the simplification of ReplaceCallOperand but either it's not called enough to matter or the addition of an extra use for this negated the improvement.

For fun here's the PIN data: https://1drv.ms/x/s!Av4baJYSo5pjgtFn8rufpZgHaeRGog?e=I5hlUc

The main reason I keep using PIN is that it can actually produce a number like 0.00% 😄. From time to time I compare an unmodified JIT and I've never seen diffs larger than 0.01%.

Copy link
Copy Markdown

@sandreenko sandreenko left a comment

Choose a reason for hiding this comment

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

LGTM

@sandreenko sandreenko merged commit afb9ca8 into dotnet:master Sep 30, 2019
@mikedn mikedn deleted the no-call-list branch October 5, 2019 07:12
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants