<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </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 - Inliner loses the original alignment for passing by value argument"
   href="https://bugs.llvm.org/show_bug.cgi?id=46433">46433</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Inliner loses the original alignment for passing by value argument
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </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>enhancement
          </td>
        </tr>

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

        <tr>
          <th>Component</th>
          <td>Interprocedural Optimizations
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>igor.breger@intel.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Looks like the passing of the struct by value, to be inlined into a memcpy with
align 1 source pointer casted to i8*, to be sroa’d, loses the original
alignment. In this case target sensitive to  alignment generate sub-optimal
code.


C code example
        typedef struct
        {    
                int* ptr1;
                int* ptr2;
                int part;
        } LabelsType ;


        int call1(LabelsType _labels, int tileNum) { 
                return _labels.ptr1[tileNum];
        }

        int test(LabelsType * t)
        {
                return call1(*t, 6);
        }


clang -O0 -S -emit-llvm

%struct.LabelsType = type { i32*, i32*, i32 }

define dso_local i32 @call1(%struct.LabelsType* byval(%struct.LabelsType) align
8 %_labels, i32 %tileNum) {
entry:
  %tileNum.addr = alloca i32, align 4
  store i32 %tileNum, i32* %tileNum.addr, align 4
  %ptr1 = getelementptr inbounds %struct.LabelsType, %struct.LabelsType*
%_labels, i32 0, i32 0
                                                                               
                                # originally we have align 8
  %0 = load i32*, i32** %ptr1, align 8                              

  %1 = load i32, i32* %tileNum.addr, align 4
  %idxprom = sext i32 %1 to i64
  %arrayidx = getelementptr inbounds i32, i32* %0, i64 %idxprom
  %2 = load i32, i32* %arrayidx, align 4
  ret i32 %2
}

define dso_local i32 @test(%struct.LabelsType* %t) {
entry:
  %t.addr = alloca %struct.LabelsType*, align 8
  store %struct.LabelsType* %t, %struct.LabelsType** %t.addr, align 8
  %0 = load %struct.LabelsType*, %struct.LabelsType** %t.addr, align 8
  %call = call i32 @call1(%struct.LabelsType* byval(%struct.LabelsType) align 8
%0, i32 6)
  ret i32 %call
}

opt -S --inline -instcombine -sroa -instcombine   <opt0 file>

define dso_local i32 @call1(%struct.LabelsType* byval(%struct.LabelsType) align
8 %_labels, i32 %tileNum) {
entry:
  %ptr1 = getelementptr inbounds %struct.LabelsType, %struct.LabelsType*
%_labels, i64 0, i32 0
  %0 = load i32*, i32** %ptr1, align 8
  %idxprom = sext i32 %tileNum to i64
  %arrayidx = getelementptr inbounds i32, i32* %0, i64 %idxprom
  %1 = load i32, i32* %arrayidx, align 4
  ret i32 %1
}

define dso_local i32 @test(%struct.LabelsType* %t) {
entry:
  %.sroa.0.0..cast.sroa_idx = getelementptr inbounds %struct.LabelsType,
%struct.LabelsType* %t, i64 0, i32 0
                                                                               
                                      # we got align 1  
  %.sroa.0.0.copyload = load i32*, i32** %.sroa.0.0..cast.sroa_idx, align 1
  %arrayidx.i = getelementptr inbounds i32, i32* %.sroa.0.0.copyload, i64 6
  %0 = load i32, i32* %arrayidx.i, align 4
  ret i32 %0
}


For similar code (manual inlining) 

int test1(LabelsType * t)
{
   return t->ptr1[6];
}

We got align 8 load  ( %0 = load i32*, i32** %ptr1, align 8 ):

define dso_local i32 @test1(%struct.LabelsType* nocapture readonly %t)
local_unnamed_addr #0 {
entry:
  %ptr1 = getelementptr inbounds %struct.LabelsType, %struct.LabelsType* %t,
i64 0, i32 0
  %0 = load i32*, i32** %ptr1, align 8, !tbaa !2
  %arrayidx = getelementptr inbounds i32, i32* %0, i64 6
  %1 = load i32, i32* %arrayidx, align 4, !tbaa !8
  ret i32 %1
}</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>