[X86] Invalid MMO due to EnablePromoteAnyextLoad
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Consider something like this:
```llvm
define void @test(ptr %p) nounwind {
%x = load i32, ptr %p
%y = load i16, ptr %p, align 4
call void @use(i32 %x, i16 %y)
ret void
}
declare void @use(i32, i16)
```
The pre-isel DAG contains:
```
t22: i32,ch = load<(load (s16) from %ir.p, align 4), anyext from i16> t0, t2, undef:i64
t5: i32,ch = load<(load (s32) from %ir.p)> t0, t2, undef:i64
```
During isel, both are morphed into the same node:
```
t5: i32,ch = MOV32rm t2, TargetConstant:i8<1>, Register:i64 $noreg, TargetConstant:i32<0>, Register:i16 $noreg, t0
```
Notably, it gets the MMO from the anyext load, which means that we claim that this only reads 2 rather than 4 bytes.
In more complex examples, this can result in a miscompile, because the load may be moved past a clobbering store on the upper two bytes.
Relevant code here is https://github.com/llvm/llvm-project/blob/3dd75651e5d6d369fb94a22efb4af15368b0511a/llvm/lib/Target/X86/X86InstrFragments.td#L678-L686 which matches a sufficiently aligned anyext load as a normal load, and then https://github.com/llvm/llvm-project/blob/3dd75651e5d6d369fb94a22efb4af15368b0511a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp#L4462-L4477 which just copies over memory operands from the original node. This means that in cases where the node is CSEd, whatever MMO was on the last one wins.
Contributor guide
Assessment
This issue has not been assessed yet.