<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 - Clang generates wrong alignment on packed structs (looks like #5598 again)"
href="https://bugs.llvm.org/show_bug.cgi?id=47824">47824</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Clang generates wrong alignment on packed structs (looks like #5598 again)
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>10.0
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</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>LLVM Codegen
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>femtium@protonmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>Created <span class=""><a href="attachment.cgi?id=24050" name="attach_24050" title="minimal-poc.c">attachment 24050</a> <a href="attachment.cgi?id=24050&action=edit" title="minimal-poc.c">[details]</a></span>
minimal-poc.c
Consider this simple test case, test1.c:
```c
struct a { int x; };
struct b { int x; };
void test(struct a *a, struct b *b)
{
a->x = b->x;
}
```
And this other test case, test2.c:
```c
struct __attribute__((packed)) a { int x; };
struct b { int x; };
void test(struct a *a, struct b *b)
{
a->x = b->x;
}
```
Both of the test() functions write sizeof(int) to offset 0 of a struct. One
would expect them to behave identically. Indeed, on x86, they generate the
exact same code. (with -O1 or -Os: "mov, mov, ret")
However, they do not generate the same IR. Here's a diff of the .ll output:
```diff
%x1 = getelementptr inbounds %struct.a, %struct.a* %2, i32 0, i32 0
- store i32 %1, i32* %x1, align 4
+ store i32 %1, i32* %x1, align 1
ret void
}
```
This does not change the generated code on X86, since that architecture
supports unaligned memory access. However, on e.g. RISCV:
```asm
test1:
lw a1, 0(a1)
sw a1, 0(a0)
ret
```
vs
```asm
test2:
lw a1, 0(a1)
sb a1, 0(a0)
srli a2, a1, 24
sb a2, 3(a0)
srli a2, a1, 16
sb a2, 2(a0)
srli a1, a1, 8
sb a1, 1(a0)
ret
```
If I manually hack the following code into the target:
```c++
+bool FooTargetLowering::allowsMisalignedMemoryAccesses(EVT VT, unsigned
AddrSpace,
+ unsigned Align,
+ MachineMemOperand::Flags Flags,
+ bool *Fast) const {
+ return true;
+}
```
Then the code generation is once again identical between the two cases.
Obviously, this is only valid if the target supports unaligned access.
Here are my thoughts about the situation:
1) At a glance, this look like #5598 has resurfaced.
2) #5598 mentions a test for x86_64. If there is indeed a regression test,
x86_64 is a bad choice, since the problem is very unlikely (guaranteed?) not to
show up on this arch
3) I think the generated IR itself is *wrong*. I can understand that an
unaligned field store would be "align 1", but surely there's no need to do this
for naturally-aligned fields?
I don't know the deeper cause of this, but I hope this simple test case can
help shed some light on what is going on.
Attached file `minimal-poc.c`, identical to `test2.c` mentioned inline in this
report.</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>