diff options
-rw-r--r-- | llvm/lib/Transforms/Scalar/SROA.cpp | 10 | ||||
-rw-r--r-- | llvm/test/Transforms/SROA/basictest.ll | 36 |
2 files changed, 43 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index a5c2f3067ed..446c2d38c10 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -3372,11 +3372,15 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { for (auto &P : AS.partitions()) { for (Slice &S : P) { Instruction *I = cast<Instruction>(S.getUse()->getUser()); - if (!S.isSplittable() ||S.endOffset() <= P.endOffset()) { - // If this was a load we have to track that it can't participate in any - // pre-splitting! + if (!S.isSplittable() || S.endOffset() <= P.endOffset()) { + // If this is a load we have to track that it can't participate in any + // pre-splitting. If this is a store of a load we have to track that + // that load also can't participate in any pre-splitting. if (auto *LI = dyn_cast<LoadInst>(I)) UnsplittableLoads.insert(LI); + else if (auto *SI = dyn_cast<StoreInst>(I)) + if (auto *LI = dyn_cast<LoadInst>(SI->getValueOperand())) + UnsplittableLoads.insert(LI); continue; } assert(P.endOffset() > S.beginOffset() && diff --git a/llvm/test/Transforms/SROA/basictest.ll b/llvm/test/Transforms/SROA/basictest.ll index 7b5daa9d782..968669ad4f6 100644 --- a/llvm/test/Transforms/SROA/basictest.ll +++ b/llvm/test/Transforms/SROA/basictest.ll @@ -1633,3 +1633,39 @@ entry: %load = load i16, i16* %bc2 ret i16 %load } + +%struct.STest = type { %struct.SPos, %struct.SPos } +%struct.SPos = type { float, float } + +define void @PR25873(%struct.STest* %outData) { +; CHECK-LABEL: @PR25873( +; CHECK: store i32 1123418112 +; CHECK: store i32 1139015680 +; CHECK: %[[HIZEXT:.*]] = zext i32 1139015680 to i64 +; CHECK: %[[HISHL:.*]] = shl i64 %[[HIZEXT]], 32 +; CHECK: %[[HIMASK:.*]] = and i64 undef, 4294967295 +; CHECK: %[[HIINSERT:.*]] = or i64 %[[HIMASK]], %[[HISHL]] +; CHECK: %[[LOZEXT:.*]] = zext i32 1123418112 to i64 +; CHECK: %[[LOMASK:.*]] = and i64 %[[HIINSERT]], -4294967296 +; CHECK: %[[LOINSERT:.*]] = or i64 %[[LOMASK]], %[[LOZEXT]] +; CHECK: store i64 %[[LOINSERT]] +entry: + %tmpData = alloca %struct.STest, align 8 + %0 = bitcast %struct.STest* %tmpData to i8* + call void @llvm.lifetime.start(i64 16, i8* %0) + %x = getelementptr inbounds %struct.STest, %struct.STest* %tmpData, i64 0, i32 0, i32 0 + store float 1.230000e+02, float* %x, align 8 + %y = getelementptr inbounds %struct.STest, %struct.STest* %tmpData, i64 0, i32 0, i32 1 + store float 4.560000e+02, float* %y, align 4 + %m_posB = getelementptr inbounds %struct.STest, %struct.STest* %tmpData, i64 0, i32 1 + %1 = bitcast %struct.STest* %tmpData to i64* + %2 = bitcast %struct.SPos* %m_posB to i64* + %3 = load i64, i64* %1, align 8 + store i64 %3, i64* %2, align 8 + %4 = bitcast %struct.STest* %outData to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %4, i8* %0, i64 16, i32 4, i1 false) + call void @llvm.lifetime.end(i64 16, i8* %0) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind |