[llvm] [LLVM][DAGCombiner] Look through freeze when combining extensions of loads (PR #175022)
David Sherwood via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 15 08:40:25 PST 2026
david-arm wrote:
Hi @RKSimon @sdesmalen-arm, thanks for your comments. I thought it was easier to address all the comments here since there was some overlap between them.
In this latest version I have added support for cases where we have freeze(load(..)) and there are multiple uses due to the chain only. This permits optimisation of more cases as you can see with the last commit. I've also used @RKSimon's suggestion of adding AssertSext and AssertZext to aid optimisations, although it required adding new splitting legalisation code for AssertSext.
I tried adding support for multiple uses of the freeze itself, but ran into various issues:
For scalar types I hit a lowering issue for test knownbits_zext_in_reg in llvm/test/CodeGen/X86/known-bits.ll that I couldn't see any obvious way to resolve in generic code. Without the optimisation the final DAG looks like:
```
Optimized legalized selection DAG: %bb.0 'knownbits_zext_in_reg:BB'
SelectionDAG has 21 nodes:
t0: ch,glue = EntryToken
t3: i32,ch = load<(load (s32) from %fixed-stack.0)> t0, FrameIndex:i32<-1>, undef:i32
t5: i8,ch = load<(load (s8) from %ir.0)> t0, t3, undef:i32
t8: i8 = freeze t5
t70: i32 = zero_extend t8
t76: i32 = mul t70, Constant:i32<101>
t66: i32 = srl t76, Constant:i8<14>
t69: i8 = truncate t66
t12: ch = CopyToReg t0, Register:i8 %0, t69
t72: i32 = mul t70, Constant:i32<177>
t58: i32 = srl t72, Constant:i8<14>
t61: i8 = truncate t58
t16: ch = CopyToReg t0, Register:i8 %1, t61
t17: ch = TokenFactor t12, t16
```
and with the optimisation it looks like this:
```
Optimized legalized selection DAG: %bb.0 'knownbits_zext_in_reg:BB'
SelectionDAG has 23 nodes:
t0: ch,glue = EntryToken
t3: i32,ch = load<(load (s32) from %fixed-stack.0)> t0, FrameIndex:i32<-1>, undef:i32
t33: i16,ch = load<(load (s8) from %ir.0), zext from i8> t0, t3, undef:i32
t34: i16 = freeze t33
t77: i32 = zero_extend t34
t73: i32 = AssertZext t77, ValueType:ch:i8
t83: i32 = mul t73, Constant:i32<101>
t66: i32 = srl t83, Constant:i8<14>
t69: i8 = truncate t66
t12: ch = CopyToReg t0, Register:i8 %0, t69
t75: i32 = mul t73, Constant:i32<177>
t59: i32 = srl t75, Constant:i8<14>
t62: i8 = truncate t59
t16: ch = CopyToReg t0, Register:i8 %1, t62
t17: ch = TokenFactor t12, t16
```
which leads to the generation of an extra mov instruction. It's not obvious to me how best to fix this - is this just an isel issue for X86 or does there need to be a DAG combine that rewrites extending load to be i8 -> i32? Also, in all other scalar tests where this made a difference it didn't actually reduce instruction count and I couldn't really see any benefit. So, I then tried restricting this multiple-use case to vectors only but I hit another roadblock. The function ExtendUsesToFormExtLoad asks the target if truncates are free, which at least for AArch64 is not true for vectors so we immediately bail out. So at least for AArch64 I couldn't write test cases to expose this issue and we need to have a target that says "vector truncates are free" and "extending vector loads are legal/desirable". Furthermore, if one of the uses is a setcc the code seems to assume it will only ever be a scalar due to the check for ConstantSDNode.
For these reason I decided to continue limiting the scope of the optimisation to cases where both the freeze and the load value have a use of one. I hope that's ok! If we find multiple-use cases in future that would be useful to optimise we can always extend this?
https://github.com/llvm/llvm-project/pull/175022
More information about the llvm-commits
mailing list