[LLVMdev] inttoptr weirdness

Jeffrey Yasskin jyasskin at google.com
Mon Dec 14 14:21:05 PST 2009


On Mon, Dec 14, 2009 at 12:27 PM, Scott Shumaker <sshumaker at gmail.com> wrote:
> Hi again.
>
> I have a complex type system in my custom language that isn't easily
> representable as LLVM IR types, so I figured I could mostly get along
> with treating my types as i8* and doing the appropriate bitcasts and
> inttoptr instructions, and doing pointer arithmetic myself (by casting
> the pointers to ints, adding the appropriate byte offsets, and then
> casting back to pointers).
>
> However, I've found some oddities.  While I have no problems
> generating IR, when I run it through the optimizer (opt -O3), it
> generates what appears to be totally wrong code.
>
> Here's my test case:
>
> I have a global called *testObj*.  It would look like this in C:
>
> struct TestObjClass
> {
>  int32 dummy1, dummy2;
>  int32* m_array;
> }
>
> extern TestObjClass* testObj;
>
> and I'm trying to access:
>
> testObj->m_array[1] = 10
>
> Theoretically, this should be a load to get the pointer to testObj
> (since it's a global), I should add 8 bytes, then do another load (to
> load the address of the array), add 4 bytes to get the array[1]
> element, and then store at that pointer the number 10.
>
> Here's my original output:
>
> @"compile-test::*testObj*" = external constant i8*              ; <i8**> [#uses=1]
>
> define void @"compile-test::__toplevel-main"() {
> entry:
>        store i8* null, i8** @"compile-test::*testObj*"

I'm surprised this store got optimized out, even though LLVM can
optimize away the subsequent load. Writing to an external global
variable is a visible side-effect, and unless there's other undefined
behavior, LLVM shouldn't remove it.

>        %1 = load i8** @"compile-test::*testObj*"               ; <i8*> [#uses=1]
>        %2 = ptrtoint i8* %1 to i32             ; <i32> [#uses=1]
>        %3 = add i32 %2, 8              ; <i32> [#uses=1]
>        %4 = inttoptr i32 %3 to i8*             ; <i8*> [#uses=1]

You may be able to save some instructions (and maybe give the
optimizers more information) by replacing the above with

  %4 = getelementptr i8* %1, i32 8

That'll be equivalent to the inttoptr(ptrtoint(%4) + 8) on systems
with 8-bit bytes.

>        %5 = load i8* %4                ; <i8> [#uses=1]
>        %6 = inttoptr i8 %5 to i8*              ; <i8*> [#uses=1]
>        %7 = ptrtoint i8* %6 to i32             ; <i32> [#uses=1]

The above two lines look odd to me. Aren't they equivalent to

  %7 = zext i8 %5 to i32

?

>        %8 = add i32 %7, 4              ; <i32> [#uses=1]
>        %9 = inttoptr i32 %8 to i8*             ; <i8*> [#uses=1]
>        %10 = bitcast i8* %9 to i32*            ; <i32*> [#uses=1]
>        store i32 10, i32* %10

And then here, if I'm not mistaken, you're converting %5, which is an
i8, that is 0<=%5<256, to a pointer, and then storing through it.
Unless you're on an embedded system, that's a guaranteed segfault,
right?


All that said, in the future you can produce a better bug report by
trying to find which pass is making the surprising transformation. See
http://llvm.org/docs/Bugpoint.html for instructions on using bugpoint
to automatically reduce the list of passes.

>        ret void
> }
>
> This seems right to me.  However, when I run it through opt -O3 and
> the through llvm-dis:
>
> @"compile-test::*testObj*" = external constant i8*              ; <i8**> [#uses=1]
> define void @"compile-test::__toplevel-main"() {
> entry:
>        %0 = load i8* inttoptr (i64 8 to i8*), align 8          ; <i8> [#uses=1]
>        %1 = inttoptr i8 %0 to i8*              ; <i8*> [#uses=1]
>        %2 = ptrtoint i8* %1 to i32             ; <i32> [#uses=1]
>        %3 = add i32 %2, 4              ; <i32> [#uses=1]
>        %4 = inttoptr i32 %3 to i32*            ; <i32*> [#uses=1]
>        store i32 10, i32* %4
>        ret void
> }
>
> Notice how there's no mention of compile-test::*testObj* at all.
> Instead, the first line is loading from (i64 8)!  What am I doing
> wrong?
>
> Thanks in advance,
> Scott
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>




More information about the llvm-dev mailing list