<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Clang's byval struct passing is still bad for code size"
   href="https://llvm.org/bugs/show_bug.cgi?id=31634">31634</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Clang's byval struct passing is still bad for code size
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>LLVM Codegen
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>rnk@google.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>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@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@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@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@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@Z"(%struct.ForcedByVal %fca,
%struct.ForcedByVal %fca, %struct.ForcedByVal %fca)

The %fca value would be produced by successive insertvalue or a bitcast from
i32.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>