[WIP] Ignore GCness when attempting to reuse constants#27466
Conversation
|
x64 diff: x86 diff: arm64 diff: arm32 diff: |
|
@CarolEidt Any concerns about this change? |
|
As I recall (and my recollection is somewhat faint, as this was a while ago), the original register allocation changes to reuse constants didn't distinguish the GC types, but it had to be added due to some regressions. I'll try to dig into that to see if I can figure that out. |
|
Thanks, I was afraid that you may say something like that :(. I initially tried to follow through git blame but got lost. Tried again and finally found the change in a dubious merge commit from 2015: 55d7daf Unfortunately the original commit that contained the change seems to have been lost somehow so there's no information about why the change was made. Oh well, that's unfortunate. I may need to keep the INITOBJ BLK for now to avoid CQ regressions. |
|
Actually the original commit is this: 93e7d20 Came from TFS... |
| { | ||
| case GT_CNS_INT: | ||
| if ((refPosition->treeNode->AsIntCon()->IconValue() == otherTreeNode->AsIntCon()->IconValue()) && | ||
| (varTypeGCtype(refPosition->treeNode) == varTypeGCtype(otherTreeNode))) |
There was a problem hiding this comment.
The comment for the change that added the second check in TFS was:
(emitThisGCrefRegs & regMask) == 0' assert failure.
The problem is that we were reusing a constant zero that was a TYP_REF.
The fix is to not reuse a register if it is not the same GC type.
There was a problem hiding this comment.
Ah, an assert, that doesn't necessarily mean that this change won't work. I also changed codegen to never emit a GC constant 0 so that assert should never be hit. Though I may need to do the same thing for non-0 byrefs, I'll check.
Thanks for the info!
There was a problem hiding this comment.
Yes, when @sandreenko mentioned this to me, I suspected that the assert may have been overly aggressive. Given the changes to codegen, it would seem that this is a safe change.
|
Thank you for your contribution. As announced in dotnet/coreclr#27549 this repository will be moving to dotnet/runtime on November 13. If you would like to continue working on this PR after this date, the easiest way to move the change to dotnet/runtime is:
|
|
I'm still looking into potential issues with GC reporting so this will have to wait until after repo consolidation. While it's obvious that there's no need to report constants to GC, the way GC tracking is done is a bit confusing. For example, the changes I've done in codegen do result in the emitter no longer reporting the constant register to the GC. But there's also Perhaps it's better to change all |
While attempting to minimize
GT_BLKuse (#27053) I've ran into a little CQ regression issue: INITOBJ is sometimes used to zero out both structs and primitive/reference types and the importer usesGT_BLKregardless. I cannot make it useGT_OBJbecauseClassLayoutis meant to work with structs or with stack allocated reference types, not with actual references. And anyway it doesn't make a lot of sense to generate a block op in the case of primitive/reference types.The problem is that converting it to
STIND.REF(LDNULL)results in code size regressions due to LSRA restrictions on the type of reused constants - they need to have the same GCness. The block version uses aTYP_INT0 while the non-block version usesTYP_REF0.However, I don't see any reason for the GCness of the constant type to matter because null references do not need to be reported to the GC. More generally, no constant needs to be reported to the GC because it cannot ever by a valid GC heap reference.
Removing the restriction also turns out to be a CQ improvement though I wasn't specifically looking for that.