Skip to content

Faulty load-store forwarding with non byte-sized types #81793

@bjope

Description

@bjope

Consider this example with a big-endian data layout:

target datalayout = "E"

define i8 @foo(ptr %p) {
entry:
  store i9 -1, ptr %p, align 1
  %r0 = load i8, ptr %p, align 1
  ret i8 %r0
}

If running that through instcombine the result is:

target datalayout = "E"

define i8 @foo(ptr %p) {
  store i9 -1, ptr %p, align 1
  ret i8 -1
}

Neither LLVM IR reference, nor the DataLayout, is describing where padding bits go when storing a non byte-sized type like that. In practice LLVM (at least the backends I know about) would (zero) extend up to the TypeStoreSize before storing the i9 to memory. So given a big-endian datalayout (and a 8-bit byte size) the above is a miscompile, as the load depends on the padding bits. Fora little-endian datalayout the optimization isn't totally wrong, but I don't think that LLVM should optimize this even for little-endian (afaik we have avioded such optimizations historically).

Here is an alive2 link showing that the above transformation is invalid: https://alive2.llvm.org/ce/z/LJpiuS

Assuming that we simply want to skip the transformation also for little endian, then a patch like this could solve the problem:

diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index f1dda97aa32d..b63c5078f88e 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -534,9 +534,11 @@ static Value *getAvailableLoadStore(Instruction *Inst, const Value *Ptr,
 
     TypeSize StoreSize = DL.getTypeSizeInBits(Val->getType());
     TypeSize LoadSize = DL.getTypeSizeInBits(AccessTy);
-    if (TypeSize::isKnownLE(LoadSize, StoreSize))
+    if (DL.typeSizeEqualsStoreSize(Val->getType()) &&
+        TypeSize::isKnownLE(LoadSize, StoreSize)) {
       if (auto *C = dyn_cast<Constant>(Val))
         return ConstantFoldLoadFromConst(C, AccessTy, DL);
+    }
   }

Metadata

Metadata

Assignees

Labels

llvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passesmiscompilation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions