[LLVMdev] Semantics of an Inbounds GetElementPtr
David Majnemer
david.majnemer at gmail.com
Sun May 3 18:57:55 PDT 2015
On Sun, May 3, 2015 at 6:26 PM, Nicholas White <n.j.white at gmail.com> wrote:
> Hi - I've got a question about what optimizations the "inbounds"
> keyword of "getelementptr" allows you to use. In the code below, %five
> is loaded from and inbounds offset of either a null pointer or %mem:
>
> target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
>
> define i8 @func(i8* %mem) {
> %test = icmp eq i8* %mem, null
> br i1 %test, label %done, label %mem.is.valid
> mem.is.valid:
> %1 = getelementptr inbounds i8, i8* %mem, i64 4
> store i8 5, i8* %1, align 4
> br label %done
> done:
> %after.phi = phi i8* [ %mem, %mem.is.valid ], [ null, %0 ]
> %2 = getelementptr inbounds i8, i8* %after.phi, i64 4
> %five = load i8, i8* %2, align 4
> ret i8 %five
> }
>
> According to the documentation, "the result value of the getelementptr
> is a poison value if the base pointer is not an in bounds address of
> an allocated object", so does this mean it's valid to optimise the
> function to:
>
> define i8 @func(i8* %mem) {
> %test = icmp eq i8* %mem, null
> br i1 %test, label %done, label %mem.is.valid
> mem.is.valid:
> ret i8 5
> done:
> ret i8 undef
> }
>
> Or even this:
>
> define i8 @func(i8* %mem) {
> ret i8 5
> }
>
No, neither are semantics preserving because there exists no store to
'%mem'.
Let's start by hoisting both sides of the branch into the entry block.
This will leave you with:
define i8 @func(i8* %mem) {
%test = icmp eq i8* %mem, null
%after.phi = select i1 %test, i8* null, %mem
%1 = getelementptr inbounds i8, i8* %mem, i64 4
store i8 5, i8* %1, align 4
%2 = getelementptr inbounds i8, i8* %after.phi, i64 4
%five = load i8, i8* %2, align 4
ret i8 %five
}
The SSA value '%after.phi' can be trivially simplified to '%mem', this
leaves us with:
define i8 @func(i8* %mem) {
%1 = getelementptr inbounds i8, i8* %mem, i64 4
store i8 5, i8* %1, align 4
%2 = getelementptr inbounds i8, i8* %mem, i64 4
%five = load i8, i8* %2, align 4
ret i8 %five
}
The SSA values '%1' and '%2' are equivalent, this leaves us with:
define i8 @func(i8* %mem) {
%1 = getelementptr inbounds i8, i8* %mem, i64 4
store i8 5, i8* %1, align 4
ret i8 5
}
I do not believe further simplification is possible.
> ...? This is a reduced example of something I saw while running "opt"
> on a test case that missed a null check. Thanks -
>
> Nick
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150503/9a8ac46e/attachment.html>
More information about the llvm-dev
mailing list