<p class="MsoNormal">Hi all,</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">I have a question regarding dynamic indexing into a vector
with GEP. I see that in the
ScalarReplAggregates pass in the LLVM 3.2 release the call SROA::isSafeGEP()
will now allow alloca scalarization in the case where a GEP index into a vector
isn’t a constant. My question is: what
is the expected behavior when the index is out of bounds of the vector? Is it undefined? I have an example .ll where we have an alloca
that can potentially be scalarized where the index into the vector is a
function argument and could be set to any value.</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">(scalar_repl_store_delete.ll):</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024--a64:64:64-f80:128:128-n8:16:32:64"</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">define void @test_fn(<2 x i32>* %src, <2 x i32>*
%results, i32 %alignmentOffsets) nounwind alwaysinline {</p>
<p class="MsoNormal">entry:</p>
<p class="MsoNormal"> %sPrivateStorage =
alloca [3 x <2 x i32>], align 8</p>
<p class="MsoNormal"> %0 = load <2 x
i32>* %src, align 8, !tbaa !9</p>
<p class="MsoNormal"> %arrayidx1 =
getelementptr inbounds [3 x <2 x i32>]* %sPrivateStorage, i64 0, i64 0</p>
<p class="MsoNormal"> store <2 x
i32> %0, <2 x i32>* %arrayidx1, align 8, !tbaa !9</p>
<p class="MsoNormal"> %arrayidx2 =
getelementptr inbounds <2 x i32>* %src, i64 1</p>
<p class="MsoNormal"> %1 = load <2 x
i32>* %arrayidx2, align 8, !tbaa !9</p>
<p class="MsoNormal"> %arrayidx3 =
getelementptr inbounds [3 x <2 x i32>]* %sPrivateStorage, i64 0, i64 1</p>
<p class="MsoNormal"> store <2 x
i32> %1, <2 x i32>* %arrayidx3, align 8, !tbaa !9</p>
<p class="MsoNormal"> %arrayidx4 =
getelementptr inbounds <2 x i32>* %src, i64 2</p>
<p class="MsoNormal"> %2 = load <2 x
i32>* %arrayidx4, align 8, !tbaa !9</p>
<p class="MsoNormal"> %arrayidx5 =
getelementptr inbounds [3 x <2 x i32>]* %sPrivateStorage, i64 0, i64 2</p>
<p class="MsoNormal"> store <2 x
i32> %2, <2 x i32>* %arrayidx5, align 8, !tbaa !9</p>
<p class="MsoNormal"> %idx.ext = zext i32
%alignmentOffsets to i64</p>
<p class="MsoNormal"> %add.ptr =
getelementptr inbounds [3 x <2 x i32>]* %sPrivateStorage, i64 0, i64 0,
i64 %idx.ext</p>
<p class="MsoNormal"> %3 = load i32*
%add.ptr, align 4, !tbaa !11</p>
<p class="MsoNormal"> %4 = insertelement
<2 x i32> undef, i32 %3, i32 0</p>
<p class="MsoNormal"> %splat =
shufflevector <2 x i32> %4, <2 x i32> undef, <2 x i32>
zeroinitializer</p>
<p class="MsoNormal"> store <2 x
i32> %splat, <2 x i32>* %results, align 8, !tbaa !9</p>
<p class="MsoNormal"> ret void</p>
<p class="MsoNormal">}</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">!9 = metadata !{metadata !"omnipotent char",
metadata !10}</p>
<p class="MsoNormal">!10 = metadata !{metadata !"Simple C/C++ TBAA",
null}</p>
<p class="MsoNormal">!11 = metadata !{metadata !"int", metadata !9}</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">In this example, the sequence of stores is copying the data
from %src into %sPrivateStorage with the GEP of interest being:</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"> %add.ptr =
getelementptr inbounds [3 x <2 x i32>]* %sPrivateStorage, i64 0, i64 0,
i64 %idx.ext</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">After running the line:</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">opt.exe -scalarrepl scalar_repl_store_delete.ll
-o=scalar_repl_store_delete_after.bc</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">We get:</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">(scalar_repl_store_delete_after.ll):</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">; ModuleID = 'scalar_repl_store_delete_after.bc'</p>
<p class="MsoNormal">target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024--a64:64:64-f80:128:128-n8:16:32:64"</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">define void @test_fn(<2 x i32>* %src, <2 x i32>*
%results, i32 %alignmentOffsets) nounwind alwaysinline {</p>
<p class="MsoNormal">entry:</p>
<p class="MsoNormal"> %sPrivateStorage.0 =
alloca <2 x i32>, align 8</p>
<p class="MsoNormal"> %0 = load <2 x
i32>* %src, align 8, !tbaa !0</p>
<p class="MsoNormal"> store <2 x
i32> %0, <2 x i32>* %sPrivateStorage.0, align 8, !tbaa !0</p>
<p class="MsoNormal"> %arrayidx2 =
getelementptr inbounds <2 x i32>* %src, i64 1</p>
<p class="MsoNormal"> %1 = load <2 x
i32>* %arrayidx2, align 8, !tbaa !0</p>
<p class="MsoNormal"> %arrayidx4 =
getelementptr inbounds <2 x i32>* %src, i64 2</p>
<p class="MsoNormal"> %2 = load <2 x
i32>* %arrayidx4, align 8, !tbaa !0</p>
<p class="MsoNormal"> %idx.ext = zext i32
%alignmentOffsets to i64</p>
<p class="MsoNormal"> %add.ptr =
getelementptr inbounds <2 x i32>* %sPrivateStorage.0, i32 0, i64 %idx.ext</p>
<p class="MsoNormal"> %3 = load i32*
%add.ptr, align 4, !tbaa !2</p>
<p class="MsoNormal"> %4 = insertelement
<2 x i32> undef, i32 %3, i32 0</p>
<p class="MsoNormal"> %splat =
shufflevector <2 x i32> %4, <2 x i32> undef, <2 x i32>
zeroinitializer</p>
<p class="MsoNormal"> store <2 x
i32> %splat, <2 x i32>* %results, align 8, !tbaa !0</p>
<p class="MsoNormal"> ret void</p>
<p class="MsoNormal">}</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">!0 = metadata !{metadata !"omnipotent char",
metadata !1}</p>
<p class="MsoNormal">!1 = metadata !{metadata !"Simple C/C++ TBAA",
null}</p>
<p class="MsoNormal">!2 = metadata !{metadata !"int", metadata !0}</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">The second two stores are deleted because they appear to be
dead even though that data can actually be reached by the out of bounds vector
index in the GEP. What is expected in
this case?</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">Thanks,</p>
<p class="MsoNormal">Scott</p>