[LLVMbugs] [Bug 6604] New: Combine Instructions phase generates bogus offset with some record types

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Fri Mar 12 16:00:24 PST 2010


           Summary: Combine Instructions phase generates bogus offset with
                    some record types
           Product: new-bugs
           Version: 2.6
          Platform: All
        OS/Version: MacOS X
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: bugzilla at quickbrownfox.org
                CC: llvmbugs at cs.uiuc.edu

I'm working on a toy compiler for a functional language that uses closures, and
I believe LLVM incorrectly optimizes access to the closure fields when they're
the result of a function. This started happening when I began compiling to
"untyped" LLVM assembly by making liberal use of of the bitcast operator.

Here's a minimal example, where I call a function and interpret the result type
as record containing a function and its argument.

%record = type { i32 (i32)*, i32}
declare i8* @mystery();

define i32 @broken()
    %1 = call i8* @mystery();
    %2 = bitcast i8* %1 to %record*;
    %funcRef = getelementptr %record* %2, i32 0, i32 0;
    %func = load i32 (i32)** %funcRef;
    %argRef = getelementptr %record* %2, i32 0, i32 1;
    %arg = load i32* %argRef;

    %res = call i32 %func(i32 %arg);
    ret i32 %res;

And here's the function after running opt -instcombine:

define i32 @broken() {
  %1 = call i8* @mystery()                        ; <i8*> [#uses=2]
  %funcRef = bitcast i8* %1 to i32 (i32)**        ; <i32 (i32)**> [#uses=1]
  %func = load i32 (i32)** %funcRef               ; <i32 (i32)*> [#uses=1]
  %argRef = getelementptr i8* %1, i64 8           ; <i8*> [#uses=1]
  %2 = bitcast i8* %argRef to i32*                ; <i32*> [#uses=1]
  %arg = load i32* %2                             ; <i32> [#uses=1]
  %res = call i32 %func(i32 %arg)                 ; <i32> [#uses=1]
  ret i32 %res

Note how the second member of the record is being accessed with a byte offset
of 8, instead of 4.
* Changing the order of the fields in the record doesn't help.
* Declaring @mystery to return a record type directly, instead of bitcasting
from i8*, will fix it.
* A similar example that takes a { i32, i32 } and adds the fields works fine.

So the bug seems to be due to casting a value to a record containing a function
pointer, and then accessing the fields of that record.

Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.

More information about the llvm-bugs mailing list