GCC may incorrectly generate bswap instructions for code not doing a correct swap. This can be seen by running the function from testsuite/gcc.dg/pr40501.c as typedef long int int64_t; __attribute__((noinline)) int64_t swap64 (int64_t n) { return (((n & (((int64_t) 0xff) )) << 56) | ((n & (((int64_t) 0xff) << 8)) << 40) | ((n & (((int64_t) 0xff) << 16)) << 24) | ((n & (((int64_t) 0xff) << 24)) << 8) | ((n & (((int64_t) 0xff) << 32)) >> 8) | ((n & (((int64_t) 0xff) << 40)) >> 24) | ((n & (((int64_t) 0xff) << 48)) >> 40) | ((n & (((int64_t) 0xff) << 56)) >> 56)); } int main (void) { volatile int64_t n = 0x8000000000000000l; if (swap64(n) != 0xffffffffffffff80l) __builtin_abort (); return 0; } This fails at -Os and higher optimization levels.
This subexpression has undefined behaviour: (((int64_t) 0xff) << 56).
(In reply to Andreas Schwab from comment #1) > This subexpression has undefined behaviour: (((int64_t) 0xff) << 56). I thought that was allowed in GCC as the manual says (https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gcc/Integers-implementation.html#Integers-implementation) "As an extension to the C language, GCC does not use the latitude given in C99 and C11 only to treat certain aspects of signed ‘<<’ as undefined." If not, what behavior does the manual refer to?
Confirmed. Better testcase (without the questionable undefined behavior): typedef long long int int64_t; __attribute__((noinline)) int64_t swap64 (int64_t n) { return (((n & (((int64_t) 0xff) )) << 56) | ((n & (((int64_t) 0xff) << 8)) << 40) | ((n & (((int64_t) 0xff) << 16)) << 24) | ((n & (((int64_t) 0xff) << 24)) << 8) | ((n & (((int64_t) 0xff) << 32)) >> 8) | ((n & (((int64_t) 0xff) << 40)) >> 24) | ((n & (((int64_t) 0xff) << 48)) >> 40) | ((n & ((int64_t)(0xffull << 56))) >> 56)); } int main (void) { volatile int64_t n = 0x8000000000000000l; if (swap64(n) != 0xffffffffffffff80l) __builtin_abort (); return 0; }
Mine. diff --git a/gcc/gimple-ssa-store-merging.cc b/gcc/gimple-ssa-store-merging.cc index 0640168bcc4..b80b8eac444 100644 --- a/gcc/gimple-ssa-store-merging.cc +++ b/gcc/gimple-ssa-store-merging.cc @@ -263,7 +263,7 @@ do_shift_rotate (enum tree_code code, int count) { int i, size = TYPE_PRECISION (n->type) / BITS_PER_UNIT; - unsigned head_marker; + uint64_t head_marker; if (count < 0 || count >= TYPE_PRECISION (n->type)
The master branch has been updated by Richard Biener <rguenth@gcc.gnu.org>: https://gcc.gnu.org/g:f675afa4eeac9910a2c085a95aa04d6d9f2fd8d6 commit r13-2013-gf675afa4eeac9910a2c085a95aa04d6d9f2fd8d6 Author: Richard Biener <rguenther@suse.de> Date: Wed Aug 10 15:45:22 2022 +0200 tree-optimization/106513 - fix mistake in bswap symbolic number shifts This fixes a mistake in typing a local variable in the symbolic shift routine. PR tree-optimization/106513 * gimple-ssa-store-merging.cc (do_shift_rotate): Use uint64_t for head_marker. * gcc.dg/torture/pr106513.c: New testcase.
The releases/gcc-12 branch has been updated by Richard Biener <rguenth@gcc.gnu.org>: https://gcc.gnu.org/g:ab2ca2dbd528f0564b80fa0e6eda96e0237742bc commit r12-8677-gab2ca2dbd528f0564b80fa0e6eda96e0237742bc Author: Richard Biener <rguenther@suse.de> Date: Wed Aug 10 15:45:22 2022 +0200 tree-optimization/106513 - fix mistake in bswap symbolic number shifts This fixes a mistake in typing a local variable in the symbolic shift routine. PR tree-optimization/106513 * gimple-ssa-store-merging.cc (do_shift_rotate): Use uint64_t for head_marker. * gcc.dg/torture/pr106513.c: New testcase. (cherry picked from commit f675afa4eeac9910a2c085a95aa04d6d9f2fd8d6)
The releases/gcc-11 branch has been updated by Richard Biener <rguenth@gcc.gnu.org>: https://gcc.gnu.org/g:ec718fb7a3a58955017cd80f6a8927afbe340fc4 commit r11-10306-gec718fb7a3a58955017cd80f6a8927afbe340fc4 Author: Richard Biener <rguenther@suse.de> Date: Wed Aug 10 15:45:22 2022 +0200 tree-optimization/106513 - fix mistake in bswap symbolic number shifts This fixes a mistake in typing a local variable in the symbolic shift routine. PR tree-optimization/106513 * gimple-ssa-store-merging.c (do_shift_rotate): Use uint64_t for head_marker. * gcc.dg/torture/pr106513.c: New testcase. (cherry picked from commit f675afa4eeac9910a2c085a95aa04d6d9f2fd8d6)
The releases/gcc-10 branch has been updated by Richard Biener <rguenth@gcc.gnu.org>: https://gcc.gnu.org/g:29ad829c93d530e75dee88d2550350c14fcaf8f6 commit r10-11038-g29ad829c93d530e75dee88d2550350c14fcaf8f6 Author: Richard Biener <rguenther@suse.de> Date: Wed Aug 10 15:45:22 2022 +0200 tree-optimization/106513 - fix mistake in bswap symbolic number shifts This fixes a mistake in typing a local variable in the symbolic shift routine. PR tree-optimization/106513 * gimple-ssa-store-merging.c (do_shift_rotate): Use uint64_t for head_marker. * gcc.dg/torture/pr106513.c: New testcase. (cherry picked from commit f675afa4eeac9910a2c085a95aa04d6d9f2fd8d6)
Fixed.