public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "kobalicek.petr at gmail dot com" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c++/103699] New: Reading or writing unaligned integers is wrongly optimized (GCC-11 and up)
Date: Tue, 14 Dec 2021 00:00:50 +0000	[thread overview]
Message-ID: <bug-103699-4@http.gcc.gnu.org/bugzilla/> (raw)

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103699

            Bug ID: 103699
           Summary: Reading or writing unaligned integers is wrongly
                    optimized (GCC-11 and up)
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kobalicek.petr at gmail dot com
  Target Milestone: ---

I have found a strange issue. When I use __attribute__((aligned(1)) on a type
to essentially annotate its lower alignment for memory load/store purposes, the
compiler would optimize such loads/stores out without any warnings. I have
never had a problem with this in GCC nor Clang, only GCC 11+ generates wrong
code for me.

Best illustrated in the code below [Compile with -O2 -std=c++17]

#include <stdint.h>

typedef uint32_t __attribute__((__aligned__(1))) UnalignedUInt32;
typedef uint64_t __attribute__((__aligned__(1))) UnalignedUInt64;

uint32_t byteswap32(uint32_t x) noexcept {
  return (x << 24) | (x >> 24) | ((x << 8) & 0x00FF0000u) | ((x >> 8) &
0x0000FF00);
}

uint64_t byteswap64(uint64_t x) noexcept {
  return ((x << 56) & 0xff00000000000000) |
         ((x << 40) & 0x00ff000000000000) |
         ((x << 24) & 0x0000ff0000000000) |
         ((x <<  8) & 0x000000ff00000000) |
         ((x >>  8) & 0x00000000ff000000) |
         ((x >> 24) & 0x0000000000ff0000) |
         ((x >> 40) & 0x000000000000ff00) |
         ((x >> 56) & 0x00000000000000ff);
}

static inline void writeU64be(void* p, uint64_t val) {
  static_cast<UnalignedUInt64*>(p)[0] = byteswap64(val);
}

static inline uint32_t readU32be(const void* p) noexcept {
  uint32_t x = static_cast<const UnalignedUInt32*>(p)[0];
  return byteswap32(x);
}

// Returns 0xBB
uint32_t test_1() {
    uint8_t array[16] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    writeU64be(array + 6, 0xAABBCCDDEEFF1213);
    return array[7];
}

// Returns 0xCC
uint32_t test_2() {
    uint8_t array[16] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    writeU64be(array + 6, 0xAABBCCDDEEFF1213);
    return array[8];
}

// Returns 0xDD
uint32_t test_3() {
    uint8_t array[16] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    writeU64be(array + 6, 0xAABBCCDDEEFF1213);
    return array[9];
}

// Returns 0xEE
uint32_t test_4() {
    uint8_t array[16] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    writeU64be(array + 6, 0xAABBCCDDEEFF1213);
    return array[10];
}

// Returns 0708090A - the write has no effect when read with readU32be()
uint32_t test_u32() {
    uint8_t array[16] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    writeU64be(array + 6, 0xAABBCCDDEEFF1213);
    return readU32be(array + 7);
}

So I'm wondering, is this a correct behavior?

It seems like a bug in the optimizer to me, because when the code is dynamic
(the data is not consts) it seems to work as expected. I have found it in a
failing unit test (GCC 11 is the only compiler that fails).

Compiler Explorer: https://godbolt.org/z/9G9cx83oq

             reply	other threads:[~2021-12-14  0:00 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-14  0:00 kobalicek.petr at gmail dot com [this message]
2021-12-14  0:21 ` [Bug c++/103699] Reading or writing a constant unaligned value is wrongly optimized causing an incorrect result " pinskia at gcc dot gnu.org
2021-12-14  0:30 ` kobalicek.petr at gmail dot com
2021-12-14  0:33 ` kobalicek.petr at gmail dot com
2021-12-14  0:38 ` kobalicek.petr at gmail dot com
2021-12-14  0:42 ` pinskia at gcc dot gnu.org
2021-12-14  1:10 ` kobalicek.petr at gmail dot com
2021-12-14  1:28 ` pinskia at gcc dot gnu.org
2021-12-14  1:43 ` kobalicek.petr at gmail dot com
2021-12-14  2:05 ` pinskia at gcc dot gnu.org
2021-12-14 12:26 ` kobalicek.petr at gmail dot com
2021-12-14 12:31 ` jakub at gcc dot gnu.org
2021-12-14 12:41 ` kobalicek.petr at gmail dot com
2021-12-14 12:57 ` jakub at gcc dot gnu.org
2021-12-14 12:58 ` jakub at gcc dot gnu.org
2021-12-14 13:09 ` kobalicek.petr at gmail dot com
2021-12-14 13:24 ` pinskia at gcc dot gnu.org
2021-12-14 13:28 ` kobalicek.petr at gmail dot com
2021-12-14 13:34 ` jakub at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-103699-4@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).