diff options
-rw-r--r-- | lib/Transforms/Scalar/ScalarReplAggregates.cpp | 11 | ||||
-rw-r--r-- | test/Transforms/ScalarRepl/dynamic-vector-gep.ll | 55 |
2 files changed, 65 insertions, 1 deletions
diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index 9fc4164cc0..bc428802e8 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -2011,8 +2011,17 @@ void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, uint64_t EltIdx = FindElementAndOffset(T, EltOffset, IdxTy); NewArgs.push_back(ConstantInt::get(IdxTy, EltIdx)); } - if (NonConstantIdx) + if (NonConstantIdx) { + Type* GepTy = T; + // This GEP has a dynamic index. We need to add "i32 0" to index through + // any structs or arrays in the original type until we get to the vector + // to index. + while (!isa<VectorType>(GepTy)) { + NewArgs.push_back(Constant::getNullValue(i32Ty)); + GepTy = cast<CompositeType>(GepTy)->getTypeAtIndex(0U); + } NewArgs.push_back(NonConstantIdx); + } Instruction *Val = NewElts[Idx]; if (NewArgs.size() > 1) { Val = GetElementPtrInst::CreateInBounds(Val, NewArgs, "", GEPI); diff --git a/test/Transforms/ScalarRepl/dynamic-vector-gep.ll b/test/Transforms/ScalarRepl/dynamic-vector-gep.ll index 48a0da9dab..af7f4398d1 100644 --- a/test/Transforms/ScalarRepl/dynamic-vector-gep.ll +++ b/test/Transforms/ScalarRepl/dynamic-vector-gep.ll @@ -80,4 +80,59 @@ entry: ret float %ret } +; CHECK: test5 +; CHECK: %[[alloc0:[\.a-z0-9]*]] = alloca <4 x float> +; CHECK: %[[alloc1:[\.a-z0-9]*]] = alloca <4 x float> +; CHECK: store <4 x float> zeroinitializer, <4 x float>* %[[alloc0]] +; CHECK: store <4 x float> zeroinitializer, <4 x float>* %[[alloc1]] +; CHECK: %ptr1 = getelementptr inbounds <4 x float>* %[[alloc0]], i32 0, i32 %idx1 +; CHECK: store float 1.000000e+00, float* %ptr1 +; CHECK: %ptr2 = getelementptr inbounds <4 x float>* %[[alloc1]], i32 0, i32 %idx2 +; CHECK: %ret = load float* %ptr2 + +%vector.pair = type { %vector.anon, %vector.anon } +%vector.anon = type { %vector } +%vector = type { <4 x float> } + +; Dynamic GEPs on vectors were crashing when the vector was inside a struct +; as the new GEP for the new alloca might not include all the indices from +; the original GEP, just the indices it needs to get to the correct offset of +; some type, not necessarily the dynamic vector. +; This test makes sure we don't have this crash. +define float @test5(i32 %idx1, i32 %idx2) { +entry: + %0 = alloca %vector.pair + store %vector.pair zeroinitializer, %vector.pair* %0 + %ptr1 = getelementptr %vector.pair* %0, i32 0, i32 0, i32 0, i32 0, i32 %idx1 + store float 1.0, float* %ptr1 + %ptr2 = getelementptr %vector.pair* %0, i32 0, i32 1, i32 0, i32 0, i32 %idx2 + %ret = load float* %ptr2 + ret float %ret +} + +; CHECK: test6 +; CHECK: %[[alloc0:[\.a-z0-9]*]] = alloca <4 x float> +; CHECK: %[[alloc1:[\.a-z0-9]*]] = alloca <4 x float> +; CHECK: store <4 x float> zeroinitializer, <4 x float>* %[[alloc0]] +; CHECK: store <4 x float> zeroinitializer, <4 x float>* %[[alloc1]] +; CHECK: %ptr1 = getelementptr inbounds <4 x float>* %[[alloc0]], i32 0, i32 %idx1 +; CHECK: store float 1.000000e+00, float* %ptr1 +; CHECK: %ptr2 = getelementptr inbounds <4 x float>* %[[alloc1]], i32 0, i32 %idx2 +; CHECK: %ret = load float* %ptr2 + +%array.pair = type { [2 x %array.anon], %array.anon } +%array.anon = type { [2 x %vector] } + +; This is the same as test5 and tests the same crash, but on arrays. +define float @test6(i32 %idx1, i32 %idx2) { +entry: + %0 = alloca %array.pair + store %array.pair zeroinitializer, %array.pair* %0 + %ptr1 = getelementptr %array.pair* %0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 %idx1 + store float 1.0, float* %ptr1 + %ptr2 = getelementptr %array.pair* %0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 %idx2 + %ret = load float* %ptr2 + ret float %ret +} + declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1) |