llvm / llvm/llvm-project

[X86] Invalid MMO due to EnablePromoteAnyextLoad

Open
#194,853 2 comments 0 reactions 1 assignee Claimed by @nikic View on GitHub
backend:X86 miscompilation
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.