Issue |
89060
|
Summary |
MemOperands not updated during ISel argument copy elision, may lead to miscompile
|
Labels |
new issue
|
Assignees |
|
Reporter |
mikaelholmen
|
Reproduce with: 06eedffe0d27
```
llc bbi-94617_3.ll -o - -debug
```
[bbi-94617_3.ll.gz](https://github.com/llvm/llvm-project/files/15010509/bbi-94617_3.ll.gz)
If we look at the debug printouts, in "Initial selection DAG:" we get
```
SelectionDAG has 29 nodes:
t0: ch,glue = EntryToken
t2: i32,ch = CopyFromReg t0, Register:i32 %0
t3: i16 = truncate t2
t5: i32,ch = CopyFromReg t0, Register:i32 %1
t6: i16 = truncate t5
t8: i32,ch = CopyFromReg t0, Register:i32 %2
t9: i16 = truncate t8
t11: i32,ch = CopyFromReg t0, Register:i32 %3
t12: i16 = truncate t11
t14: i32,ch = CopyFromReg t0, Register:i32 %4
t15: i16 = truncate t14
t17: i32,ch = CopyFromReg t0, Register:i32 %5
t18: i16 = truncate t17
t21: i16,ch = load<(load (s16) from %fixed-stack.0)> t0, FrameIndex:i64<-1>, undef:i64
t23: i64 = Constant<0>
t24: ch = store<(store (s16) into @v_781, align 1)> t21:1, t21, GlobalAddress:i64<ptr @v_781> 0, undef:i64
t26: ch = store<(store (s16) into %ir.param.addr, align 1)> t24, Constant:i16<666>, FrameIndex:i64<-1>, undef:i64
t28: ch = X86ISD::RET_GLUE t26, TargetConstant:i32<0>
```
Especially consider
```
t21: i16,ch = load<(load (s16) from %fixed-stack.0)> t0, FrameIndex:i64<-1>, undef:i64
```
and
```
t26: ch = store<(store (s16) into %ir.param.addr, align 1)> t24, Constant:i16<666>, FrameIndex:i64<-1>, undef:i64
```
The load and store both access "FrameIndex:i64<-1>", but the MemOperands look like
```
load (s16) from %fixed-stack.0
```
and
```
store (s16) into %ir.param.addr, align 1
```
so they access exactly the same memory on the stack, but according to the MemOperands it looks like they access different objects? I think this is wrong.
If we look further at the debug printouts at "MI Scheduling" we get
```
SU(0): %6:gr16 = MOV16rm %fixed-stack.0, 1, $noreg, 0, $noreg :: (load (s16) from %fixed-stack.0, align 16)
# preds left : 0
# succs left : 1
# rdefs left : 0
Latency : 4
Depth : 0
Height : 4
Successors:
SU(2): Data Latency=4 Reg=%6
Single Issue : false;
[...]
SU(2): MOV16mr %7:gr64, 1, $noreg, 0, $noreg, %6:gr16 :: (store (s16) into @v_781, align 1)
# preds left : 2
# succs left : 0
# rdefs left : 0
Latency : 1
Depth : 4
Height : 0
Predecessors:
SU(1): Data Latency=4 Reg=%7
SU(0): Data Latency=4 Reg=%6
Single Issue : false;
SU(3): MOV16mi %fixed-stack.0, 1, $noreg, 0, $noreg, 666 :: (store (s16) into %ir.param.addr, align 16)
# preds left : 0
# succs left : 0
# rdefs left : 0
Latency : 1
Depth : 0
Height : 0
Single Issue : false;
```
So there is no dependency whatsoever between the load, SU(0) and the store SU(3), even if they access the same memory.
On my downstream target this then lead to a miscompile when the scheduler choose to change the order of the load and store.
I think the problem is that SelectionDAGISel::LowerArguments and tryToElideArgumentCopy does rewrites and change the FI used in some instructions, but they leave the MemOperands unchanged.
This seems to be old but it recently lead to a miscompile for my target when the load and store suddenly executed in the wrong order.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs