JIT: Do not propagate some constants#70378
Conversation
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsLet's see what Diffs think. This might ruin some Lowering optimizations which expect constant values but I expect to see more benefits than regressions from this. Closes #70355
|
src/coreclr/jit/assertionprop.cpp
Outdated
| } | ||
| #elif TARGET_XARCH | ||
| // All integer constants are cheap to materialize on xarch | ||
| keepPropagating = true; |
There was a problem hiding this comment.
Is this right?
Those that fit in 8-bits (generally sign-extended, but sometimes zero-extended) are often (but not always) containable, but if its 2-, 4-, or 8-bytes` then it generally needs a separate instruction and is more expensive.
There was a problem hiding this comment.
@tannergooding I agree but in this PR I only try to avoid memory loads - there are too many pitfalls this PR can't take into account like register-pressure, cached constants which live across calls on ABIs without callee-saved regs, etc - it's just a quick heuristic at this point
There was a problem hiding this comment.
It might be worth logging an issue for someone to experiment here a bit.
I'd expect that most cases of explicit mov reg, imm are better handled by hoisting as it impacts the size of the loop and doesn't allow optimizations in many scenarios.
There was a problem hiding this comment.
Sure thing, I am actually going to spend some time on it after this PR because it's even more important for ARM where it might ends up with 4 mov per single constant
PerfScore diffs |
|
@dotnet/jit-contrib @tannergooding @jakobbotsch PTAL |
tannergooding
left a comment
There was a problem hiding this comment.
This seems like a reasonable fix to me.
src/coreclr/jit/assertionprop.cpp
Outdated
| const unsigned ssaNum = GetSsaNumForLocalVarDef(tree); | ||
| if (ssaNum != SsaConfig::RESERVED_SSA_NUM) | ||
| { | ||
| BasicBlock* defBlock = lvaTable[lclNum].GetPerSsaData(ssaNum)->GetBlock(); |
There was a problem hiding this comment.
Style nit: lvaTable[lclNum]. -> lvaGetDesc(lclNum)->.
General comment on the algorithm: this walks only one step up in the def chain, so if we have something like this:
var a = const;
for (...) {
var b = a;
Use(b);
}We will still propagate const to Use.
There was a problem hiding this comment.
@SingleAccretion I don't see why it would.
When we're at Use(b) and we query SsaData()->Block from b we get a's Block and it leads to "avoid propagating" path
There was a problem hiding this comment.
Ah, actually for your case b is going to be replaced with a in an earlier phase VN based copy prop
There was a problem hiding this comment.
When we're at
Use(b)and we querySsaData()->Blockfrombwe geta's Block and it leads to "avoid propagating" path
If I annotate this with blocks:
BB01:
var a = const;
for (...) {
BB02:
var b = a; // b:d:1
Use(b); // b:u:1
}I am pretty sure that when we query the def block for b:u:1, we'd get BB02, since the def b:d:1 occurs inside it.
Ah, actually for your case
bis going to be replaced withain an earlier phase VN based copy prop
I agree that copy propagation helps us here; not sure by how much because of the liveness constraints it has.
In any case, I also agree that there is no reason, for now, to complicate the code with a full UD chain walk, because we are pretty much targeting people hoisting constants out of loops by hands.
Co-authored-by: Tanner Gooding <tagoo@outlook.com>
|
@SingleAccretion does it look good now? |
Yeah, I ran SPMI with |
Let's see what Diffs think.
Jit always try to propagate single-def constant values but it's not always a good thing, e.g. constant vectors and doubles end up as memory loads and we don't want to propagate them inside loops etc. Same about long integers (e.g. handles) on arm64
This might ruin some Lowering optimizations which expect constant values but I expect to see more benefits than regressions from this.
Closes #70355