[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
http://llvm.org/bugs/show_bug.cgi?id=2648
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
two
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() {
entry:
%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>
[#uses=1]
%tmp712.ins = or i64 %out.in11.mask, %tmp712 ; <i64>
[#uses=1]
%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>
[#uses=1]
%tmp8910.ins = or i64 %out.in.mask, %tmp8910 ; <i64>
[#uses=2]
%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
doesn't
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 {
entry:
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
bitpacked
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
all
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