[llvm-bugs] [Bug 31634] New: Clang's byval struct passing is still bad for code size

via llvm-bugs llvm-bugs at lists.llvm.org
Fri Jan 13 09:36:41 PST 2017


https://llvm.org/bugs/show_bug.cgi?id=31634

            Bug ID: 31634
           Summary: Clang's byval struct passing is still bad for code
                    size
           Product: clang
           Version: unspecified
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: normal
          Priority: P
         Component: LLVM Codegen
          Assignee: unassignedclangbugs at nondot.org
          Reporter: rnk at google.com
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

I'm convinced we should avoid it because of this example:

struct ForcedByVal {
  ForcedByVal();
  char a, b, c, d;
};
void g(ForcedByVal, ForcedByVal, ForcedByVal);
void f() {
  ForcedByVal o;
  g(o, o, o);
}


This generates the following IR:

define void @"\01?f@@YAXXZ"() local_unnamed_addr #0 {
entry:
  %o = alloca i32, align 4
  %tmpcast3 = bitcast i32* %o to %struct.ForcedByVal*
  %agg.tmp = alloca i32, align 4
  %tmpcast = bitcast i32* %agg.tmp to %struct.ForcedByVal*
  %agg.tmp1 = alloca i32, align 4
  %tmpcast4 = bitcast i32* %agg.tmp1 to %struct.ForcedByVal*
  %agg.tmp2 = alloca i32, align 4
  %tmpcast5 = bitcast i32* %agg.tmp2 to %struct.ForcedByVal*
  %0 = bitcast i32* %o to i8*
  call void @llvm.lifetime.start(i64 4, i8* nonnull %0) #3
  %call = call x86_thiscallcc %struct.ForcedByVal*
@"\01??0ForcedByVal@@QAE at XZ"(%struct.ForcedByVal* nonnull %tmpcast3)
  %1 = load i32, i32* %o, align 4
  store i32 %1, i32* %agg.tmp, align 4
  store i32 %1, i32* %agg.tmp1, align 4
  store i32 %1, i32* %agg.tmp2, align 4
  call void @"\01?g@@YAXUForcedByVal@@00 at Z"(%struct.ForcedByVal* byval nonnull
align 4 %tmpcast5, %struct.ForcedByVal* byval nonnull align 4 %tmpcast4,
%struct.ForcedByVal* byval nonnull align 4 %tmpcast)
  call void @llvm.lifetime.end(i64 4, i8* nonnull %0) #3
  ret void
}

Which generates this assembly:

"?f@@YAXXZ":                            # @"\01?f@@YAXXZ"
# BB#0:                                 # %entry
        subl    $28, %esp
        leal    24(%esp), %ecx
        calll   "??0ForcedByVal@@QAE at XZ"
        movl    24(%esp), %eax   # Needed
        movl    %eax, 20(%esp)
        movl    %eax, 16(%esp)
        movl    %eax, 12(%esp)
        movl    20(%esp), %eax
        movl    %eax, 8(%esp)    # Needed
        movl    16(%esp), %eax
        movl    %eax, 4(%esp)    # Needed
        movl    12(%esp), %eax
        movl    %eax, (%esp)     # Needed
        calll   "?g@@YAXUForcedByVal@@00 at Z"
        addl    $28, %esp
        retl

All the above loads and stores not tagged "# Needed" are completely redundant.

Clang has to create three temporary allocas to be the source of the byval
parameter. It's possible that we can elide those allocas in the frontend, but
memcpyopt would have to get a lot smarter about reasoning about byval to remove
those copies in the middle end.

I think instead of improving our reasoning about byval, we should migrate away
from it and move towards FCAs in arguments. The LLVM prototype would look like
this:

  call void @"\01?g@@YAXUForcedByVal@@00 at Z"(%struct.ForcedByVal %fca,
%struct.ForcedByVal %fca, %struct.ForcedByVal %fca)

The %fca value would be produced by successive insertvalue or a bitcast from
i32.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20170113/a6d1a752/attachment.html>


More information about the llvm-bugs mailing list