[LLVMbugs] [Bug 2648] New: Scalarrepl and inliner produce messy IR when returning small structs

bugzilla-daemon at cs.uiuc.edu bugzilla-daemon at cs.uiuc.edu
Thu Aug 7 06:08:35 PDT 2008


           Summary: Scalarrepl and inliner produce messy IR when returning
                    small structs
           Product: libraries
           Version: trunk
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Scalar Optimizations
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: matthijs at stdin.nl
                CC: llvmbugs at cs.uiuc.edu

Created an attachment (id=1901)
 --> (http://llvm.org/bugs/attachment.cgi?id=1901)
Simple testcase

I've attached a simple C file that has a function that returns a struct with
ints. When compiling this using clang and then running it through opt
-std-compile-opts, this generates messy code.

I've also attached testcase.ll, which is the IR produced by clang.

The problem seems to be caused by scalarrepl being run after the inliner, so to
reproduce, you can run "llvm-as < testcase.ll | opt -inline -scalarrepl
-instcombine" which produces the following uglyness ( the instcombine slightly
reduces the uglyness, but not by much):

  define i32 @run() {
          %call.i = call i32 @bar( )              ; <i32> [#uses=1]
          %call2.i = call i32 @bar( )             ; <i32> [#uses=1]
          %tmp712 = zext i32 %call.i to i64               ; <i64> [#uses=1]
          %out.in11.mask = and i64 undef, -4294967296             ; <i64>
          %tmp712.ins = or i64 %out.in11.mask, %tmp712            ; <i64>
          %tmp89 = zext i32 %call2.i to i64               ; <i64> [#uses=1]
          %tmp8910 = shl i64 %tmp89, 32           ; <i64> [#uses=1]
          %out.in.mask = and i64 %tmp712.ins, 4294967295          ; <i64>
          %tmp8910.ins = or i64 %out.in.mask, %tmp8910            ; <i64>
          %tmp417 = trunc i64 %tmp8910.ins to i32         ; <i32> [#uses=1]
          %tmp614 = lshr i64 %tmp8910.ins, 32             ; <i64> [#uses=1]
          %tmp615 = trunc i64 %tmp614 to i32              ; <i32> [#uses=1]
          %add = add i32 %tmp417, %tmp615         ; <i32> [#uses=1]
          ret i32 %add

Running -std-compile-opts over this again doesn't change anything.

Running -instcombine before -scalarrepl removes the memmoves that clang
introduces, but replaces the alloca {i32, i32} with an alloca i64, which
help for scalarrepl and leaves the output unchanged.

Additionally, running the .c file through llvm-gcc with -O1, or with -O0 and
then through opt -std-compile-opts, we get the nice and simple:

  define i32 @run() nounwind {
          tail call i32 @bar( ) nounwind          ; <i32>:0 [#uses=1]
          tail call i32 @bar( ) nounwind          ; <i32>:1 [#uses=1]
          add i32 %1, %0          ; <i32>:2 [#uses=1]
          ret i32 %2

So, there are a number of problems here:
 * clang produces a lot of memmoves when handling structs. This is not
   functionally wrong (AFAICS), but this seems to confuse scalarrepl.
 * instcombine succesfully removes these memmoves, but introduces alloca i64's
   and bitcasts, which don't help to prevent the confusion of scalarrepl.
 * scalarrepl, in turn, lets itself be confused into producing a funky
   version of the struct, which it shouldn't need to in this case (I think).
 * Finally, none of the standard passes are able to disentangle the mess
   produced. In particular, I would have expected instcombine to see through
   those shifts, ands and truncates, but it doesn't.

I think that any (or all) of the above could (should) be fixed, but in
particular the second and third points. No more time to do more detailed
debugging, unfortunately.

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