https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89809
Bug ID: 89809 Summary: movzwl is not utilized when uint16_t is loaded with bit-shifts (while memcpy does) Product: gcc Version: 9.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: nok.raven at gmail dot com Target Milestone: --- Host: x86_64 Target: x86_64 #include <cstdint> #include <cstring> // could be just a single movzwl std::uint16_t foo(unsigned char const* p) { return static_cast<std::uint16_t>(p[0]) | (static_cast<std::uint16_t>(p[1]) << 8) ; } // the same, but for uint32_t is recognized std::uint32_t bar(unsigned char const* p) { return static_cast<std::uint32_t>(p[0]) | (static_cast<std::uint32_t>(p[1]) << 8) | (static_cast<std::uint32_t>(p[2]) << 16) | (static_cast<std::uint32_t>(p[3]) << 24) ; } // memcpy for uint16_t is also good, and generates movzwl std::uint16_t qaz(unsigned char const* p) { std::uint16_t tmp = 0; std::memcpy(&tmp, p, sizeof(tmp)); return tmp; } https://godbolt.org/z/ZQl1tF movzwl could be also utilized in other byte-size integers load. See the attachment or https://godbolt.org/z/PQwc87