[llvm-bugs] [Bug 47824] New: Clang generates wrong alignment on packed structs (looks like #5598 again)

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Oct 13 07:52:16 PDT 2020


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

            Bug ID: 47824
           Summary: Clang generates wrong alignment on packed structs
                    (looks like #5598 again)
           Product: clang
           Version: 10.0
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: LLVM Codegen
          Assignee: unassignedclangbugs at nondot.org
          Reporter: femtium at protonmail.com
                CC: llvm-bugs at lists.llvm.org, neeilans at live.com,
                    richard-llvm at metafoo.co.uk

Created attachment 24050
  --> https://bugs.llvm.org/attachment.cgi?id=24050&action=edit
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.

-- 
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/20201013/70add291/attachment.html>


More information about the llvm-bugs mailing list