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

SROA: allow reconstruction of original aggregate with OPpair #6192

Merged
merged 2 commits into from
Oct 16, 2016

Conversation

WalterBright
Copy link
Member

SROA slices an aggregate into individual variables. Hence, operations needing the original aggregate are disallowed. This PR improves that by allowing loads of the original aggregate by reconstituting it out of the slices using OPpair.

The net result is more cases of SROA can be performed.

@WalterBright WalterBright force-pushed the sroa2 branch 6 times, most recently from 5a84458 to 34fd345 Compare October 12, 2016 21:47
@andralex
Copy link
Member

LGTM - @MartinNowak wanna take a look?

@WalterBright
Copy link
Member Author

The FreeBSD 32 failure appears to be a heisenbug timeout.

@@ -88,16 +144,30 @@ static void sliceStructs_Replace(SymInfo *sia, elem *e)
//elem_print(e);
if (si >= 0 && sia[si].canSlice)
{
if (e->Eoffset == 0) // the first slice of the symbol is the same as the original
if (tysize(e->Ety) == 2 * REGSIZE)
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't you use usePair here?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, because not every use of the symbol will be 2*REGSIZE, despite usePair.

if (!sia[si].accessSlice)
{
// If never did access it as a slice, don't slice
sia[si].canSlice = false;
Copy link
Member

Choose a reason for hiding this comment

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

Using it this way, doSlice instead of canSlice would better a description.

Copy link
Member Author

Choose a reason for hiding this comment

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

I prefer can to be answering a question, and do to actually perform the work.

Copy link
Member

Choose a reason for hiding this comment

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

Well, but here it could be sliced but shouldn't be done (b/c it's not used). Anyhow...

Choose a reason for hiding this comment

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

isSliced ?

sold->Stype->Tcount++;
snew->Stype = type_fake(TYnptr);
snew->Stype = type_fake(sia[si].ty1);
Copy link
Member

Choose a reason for hiding this comment

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

Aren't ty0 and ty1 the types of the fields? Why would you use a different type for the replacement symbol?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because they may be different types. a.ptr and a.length are different, for example.

Copy link
Member

Choose a reason for hiding this comment

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

The confusing part here was that you're reusing sold for the new replacement symbol.

Copy link
Member Author

Choose a reason for hiding this comment

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

just changing its type


/* OPpair cannot handle XMM registers, cdpair() and fixresult()
*/
if (tyfloating(sia[si].ty0) || tyfloating(sia[si].ty1))
Copy link
Member

Choose a reason for hiding this comment

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

This branch is a bit confusing b/c it seems to rely on the fact that the else if branch below was run for e->E1 and e->E2 beforehand.
Would be simpler to understand if you changed the order of the branches and added a small comment.

Copy link
Member

Choose a reason for hiding this comment

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

Also notice that the condition at https://github.com/dlang/dmd/pull/6192/files#diff-22b8e2c888085072a0c7f94f80991c4eR81 does the same thing as the test here.

Copy link
Member Author

Choose a reason for hiding this comment

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

No, it doesn't rely on that at all. E1 and E2 could not have been run beforehand for OPvar, because they don't exist for OPvar elems.

Copy link
Member

@MartinNowak MartinNowak Oct 16, 2016

Choose a reason for hiding this comment

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

So what's really happening here is that a symbol could be used as fat value, but also could get sliced for field access.
Therefor you have to mutually account for the other case.
I'll comment that to make it understandable in the code.

Copy link
Member Author

Choose a reason for hiding this comment

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

It does account for the other case. I don't really know what you want to say there - the code is there in the other case.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, it just wasn't obvious how the two branches relate to each other.
They are independent b/c different parts of the expression tree can access the same symbol, one as slice, one as fat value using OPpair.

Copy link
Member

Choose a reason for hiding this comment

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

Could have been simpler to later (during slicing) check for usePair && accessSlice && (tyfloating(ty0) || tyfloating(ty1)) instead of mutating canSlice here. But I guess your XMM OPpair work obsoletes this.

Copy link
Member Author

Choose a reason for hiding this comment

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

I need to do OPpair improvements anyway, and am doing so, but I wanted to keep this PR focussed. Once OPpair is working properly, I'll come back and remove this hack.

Copy link
Member

@MartinNowak MartinNowak Sep 24, 2017

Choose a reason for hiding this comment

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

Thanks, just wasted 3 days debugging a memory corruption based on this :/.
Wasn't too well put here, but as mentioned ty0 and ty1 are still uninitialized if access as fat value happens before any access to a sliced field.

sia[si].ty0 = tybasic(e->Ety);
else
sia[si].ty1 = tybasic(e->Ety);
if (sia[si].usePair && (tyfloating(sia[si].ty0) || tyfloating(sia[si].ty1)))
Copy link
Member

Choose a reason for hiding this comment

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

This is weird, when usePair gets set above (if (sz == 2 * REGSIZE)), it expects ty0/1 to already be set. But here where the ty0/1 assignment is done, you're checking for usePair to be set earlier.
How can both cases be valid?

Copy link
Member Author

Choose a reason for hiding this comment

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

ty0/1 are defaulted to TYnptr. They are set to correct values when a slice case is encountered. If no slice cases are encountered, then slicing is not done.

@MartinNowak
Copy link
Member

Auto-merge toggled on

@MartinNowak
Copy link
Member

Added the comment

@MartinNowak MartinNowak merged commit 8699245 into dlang:master Oct 16, 2016
@WalterBright
Copy link
Member Author

Thanks, @MartinNowak

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