[Bug tree-optimization/87623] New: bytes swapped in register when comparing cause fail when comiled with -O1 or higher
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87623 Bug ID: 87623 Summary: bytes swapped in register when comparing cause fail when comiled with -O1 or higher Product: gcc Version: 8.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: george.thopas at gmail dot com Target Milestone: --- Target: x86_64-pc-linux-gnu Build: gcc version 8.2.0 (Gentoo 8.2.0-r3 p1.4) - Compare of two single char fields in two structures with different scalar_storage_order order goes wrong. Reduced test case below. - Observed in 6.3.1 and reproducible in 8.2.0 , Target x86_64-pc-linux-gnu ---[howto] passed test: $ gcc -O0 test.c $ ./a.out failed test: $ gcc -O1 test.c $ ./a.out Aborted -- [code] /* test.c */ #include struct be { unsigned short pad[1]; unsigned char a; unsigned char b; } __attribute__((scalar_storage_order("big-endian"))); typedef struct be t_be; struct le { unsigned short pad[3]; unsigned char a; unsigned char b; }; typedef struct le t_le; int a_or_b_different(t_be *x,t_le *y) { return ((x->a != y->a) || (x->b != y->b)); } int main(int argc,char *argv[]) { t_be x = { .a=1, .b=2 }; t_le y = { .a=1, .b=2 }; if (a_or_b_different(&x,&y)) abort(); return 0; } -- jbeu@bt9923 ~ $ gcc -v -O1 test.c Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /var/tmp/portage/sys-devel/gcc-8.2.0-r3/work/gcc-8.2.0/configure --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/8.2.0 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/8.2.0 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/8.2.0/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/8.2.0/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/g++-v8 --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/8.2.0/python --enable-languages=c,c++,fortran --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --enable-nls --without-included-gettext --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo 8.2.0-r3 p1.4' --disable-esp --enable-libstdcxx-time --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-multilib --with-multilib-list=m32,m64 --disable-altivec --disable-fixed-point --enable-targets=all --enable-libgomp --disable-libmudflap --disable-libssp --disable-libmpx --disable-systemtap --enable-vtable-verify --enable-libvtv --enable-lto --without-isl --enable-libsanitizer --enable-default-pie --enable-default-ssp Thread model: posix gcc version 8.2.0 (Gentoo 8.2.0-r3 p1.4) COLLECT_GCC_OPTIONS='-v' '-O1' '-mtune=generic' '-march=x86-64' /usr/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/cc1 -quiet -v bug.c -quiet -dumpbase bug.c -mtune=generic -march=x86-64 -auxbase bug -O1 -version -o /tmp/ccdpdLOi.s GNU C17 (Gentoo 8.2.0-r3 p1.4) version 8.2.0 (x86_64-pc-linux-gnu) compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version none GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring nonexistent directory "/usr/local/include" ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed /usr/include End of search list. GNU C17 (Gentoo 8.2.0-r3 p1.4) version 8.2.0 (x86_64-pc-linux-gnu) compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version none GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 91d4bd0e38b68a0f50315f89ba003c77 COLLECT_GCC_OPTIONS='-v' '-O1' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../x86_64-pc-linux-gnu/bin/as -v --64 -o /tmp/ccsw11XW.o /tmp/ccdpdLOi.s GNU assembler version 2.31.1 (x86_64-pc-linux-gnu) using BFD version (Gentoo 2.31.1 p3) 2.31.1 COMPILER_PATH=/usr/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/libexec/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gc
[Bug middle-end/87623] bytes swapped in register when comparing cause fail when compiled with -O1 or higher
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87623 --- Comment #9 from George Thopas --- (In reply to Eric Botcazou from comment #8) > Thanks for reporting the problem. And thanks for the swift resolution !
[Bug c/100804] New: storage order swapped with specific opt
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100804 Bug ID: 100804 Summary: storage order swapped with specific opt Product: gcc Version: 11.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: george.thopas at gmail dot com Target Milestone: --- /* Target: x86_64-pc-linux-gnu gcc versie 10.2.0 (Gentoo 10.2.0-r4 p5) failing: $ gcc -Wall -Wextra -O2 test.c && ./a.out Aborted passing: $ gcc -Wall -Wextra -O3 test.c && ./a.out $ gcc -Wall -Wextra -O1 test.c && ./a.out $ gcc -Wall -Wextra -O0 test.c && ./a.out no fallout with -fno-strict-aliasing -fwrapv problem goes away with adding either -fno-code-hoisting, -fno-guess-branch-probability, The example includes an unused string structure which seems to affect the problem. The odd thing is that it is never used in this code Removing the untaken else path makes the problem go away too Thanks */ #include #include #include #define BE __attribute__((scalar_storage_order("big-endian"))) struct _str { char str[10]; }; typedef struct _str t_str; struct _le { char is_val; union { int val; t_str str; } data; }; typedef struct _le t_le; union _be_data { int val; t_str str; } BE; typedef union _be_data t_be_data; struct _be { char is_val; t_be_data data; } BE; typedef struct _be t_be; void validate(t_be * in) { t_le chk = { is_val:1, data: { val:0x12345678 } }; t_le out = { }; out.is_val = in->is_val; if (out.is_val) out.data.val = in->data.val; else out.data.str = in->data.str; if (out.data.val != chk.data.val) abort(); } int main(void) { t_be val = { is_val:1, data: { val:0x12345678 } }; validate(&val); return 0; }
[Bug c/100804] storage order swapped with specific opt
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100804 --- Comment #2 from George Thopas --- After looking at the updated documentation and trying the an update kernel with warning it still leaves some things open. The updated documentation says: "Moreover, the use of type punning or aliasing to toggle the storage order is not supported; that is to say, if a given scalar object can be accessed through distinct types that assign a different storage order to it, then the behaviour is undefined" - In my example the new warning fires on a struct only having chars. I don't see how that is applicable here or how a char array could have a different storage order in either big or little endian. - Regardless of that fact. That field is also never accessed in my example code Al 2 fields of the structs actually read are consistently be (in) and the one written is (out) le. The ones compare are of the same type. Thanks again
[Bug c/100920] New: bogus warn on -Wscalar-storage-order
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100920 Bug ID: 100920 Summary: bogus warn on -Wscalar-storage-order Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: george.thopas at gmail dot com Target Milestone: --- /* * trying to use -Wscalar-storage-order on latest git version * * https://gcc.gnu.org/g:401bd4adcfda9965363b1ac3ba7e1580f15d6883 * * below test exposes what looks like 2 wrong warnings * a warning on an union where everything is big-endian * a warning on type less void pointer * * gcc -Werror test.c * * Thanks */ include struct s_1 { int val; } __attribute__((scalar_storage_order("big-endian"))); typedef struct s_1 t_1; struct s_2 { char val; } __attribute__((scalar_storage_order("big-endian"))); typedef struct s_2 t_2; struct s12 { t_1 a[1]; t_2 b[1]; } __attribute__((scalar_storage_order("big-endian"))); typedef struct s12 t_s12; /* Warning while everything is big-endian */ union u12 { t_1 a[1]; t_2 b[1]; } __attribute__((scalar_storage_order("big-endian"))); typedef union u12 t_u12; int main(void) { /* warning while assigning from a type less void pointer */ t_s12 *msg1 = __builtin_alloca(10); t_u12 *msg2 = __builtin_alloca(10); msg1->a[0].val=0; msg2->a[0].val=0; return 0;
[Bug c/100920] bogus warnings with -Wscalar-storage-order
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100920 --- Comment #2 from George Thopas --- (In reply to Eric Botcazou from comment #1) > The warning on the union is indeed an oversight, but the other is > conservatively correct, although we may make a special case for > __builtin_alloca. Hi Eric, first of all, thanks for looking into this. It may not be immediately obvious from my example but the the builtin_alloca is not the only problem. Any malloc/calloc has the same effect. Even if one requires casts at alloc time, any free will trigger the same warning. t_s12 *msg1 = (t_s12)malloc(10); free(msg1); I don't understand what the incompatibility reported is with void pointers. To my understanding they are type-less and can't be dereferenced.
[Bug c/100920] bogus warnings with -Wscalar-storage-order
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100920 --- Comment #6 from George Thopas --- (In reply to Eric Botcazou from comment #5) > Thanks for reporting the problem. Thanks for the swift fix. It nicely resolves it for the malloc/alloca ... It doesn't seem to do anything for the rest of the common idioms however when I extend the testcase. int main() { t_s12 *msg1 = __builtin_alloca(10); t_u12 *msg2 = __builtin_alloca(10); int same; msg1 = malloc (sizeof (t_s12)); msg2 = malloc (sizeof (t_u12)); memset(msg1, 0, sizeof(t_s12)); memcpy(msg2, &msg1, sizeof(t_s12)); same = memcmp(msg2, msg1, sizeof(t_s12)); free(msg1); return same; }
[Bug c/100920] bogus warnings with -Wscalar-storage-order
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100920 --- Comment #9 from George Thopas --- /* Hi Eric, 1) I noticed there's a typo in the test, (which is my fault) and may give unexpected behavior later on memcpy(msg2, &msg1, sizeof(t_s12)); => should be memcpy(msg2, msg1, sizeof(t_s12)); 2) Trying to get a platform built free of these warning, I still see quite some which match below example. Raising one for these cases is really problematic. Functions using void in stead of an explicit type are explicitly saying that the type does not matter. There never is a warning for any other type where you pass them. so I hope you can give this one another go. Thanks again for your patience. */ #include #include #define SIZE 10 struct be { int a; int b; } __attribute__((scalar_storage_order("big-endian"))); typedef struct be t_be; struct le { int a; int b; } __attribute__((scalar_storage_order("little-endian"))); typedef struct le t_le; void memset2(void *s, char c, int n) { char *d=(char *)s; for(int i=0;i
[Bug c/100653] usage of scalar_storage_order produces incorrect result
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100653 --- Comment #9 from George Thopas --- Created attachment 51025 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=51025&action=edit avoid eliminating fields with different endianess as equal Short story : Ran a bisect to find why this always works in the gcc-6 branch and has different behaviour outside. Found out what happens (see below) and attached a 2-line patch for what I assume is missing. Works for me but is it the 'right thing'(tm) todo ? Thanks. Long story: I started digging into this in the hope to get a better understanding In the last 3 years I've never seen this on the gcc-6 branch. Even though there's a tons of code and mixed endianess structures and unions validation. If I missed it, I at least needed to know at least why. The bisect ended up giving commit e7a3e0c653be4bd32f116dae06438896b7dc915b. Reverting it for test purposes in gcc-7/gcc-8 just confirmed it is the right trigger. There's obviously nothing wrong with that commit but at least it gave me a clue what to look for. To my understanding of the code : The RPO change affects evaluation order when merging and eliminating blocks. In the case of the example, the compiler ends up checking if both fields of the union are the same and can be merged/eliminated. Their both in the same location. The code currently considers different signedness and bails out, but not different endianness and eliminates one depending one evaluation order. Whatever one that is.
[Bug c/101925] New: reversed storage order when compiling with -O3 only
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101925 Bug ID: 101925 Summary: reversed storage order when compiling with -O3 only Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: george.thopas at gmail dot com Target Milestone: --- /* reversed storage order when compiling with -O3 only. this time sets up an all big-endian struct from an all little-endian one no warnings Target: x86_64-pc-linux-gnu gcc versie 11.1.0 (Gentoo 11.1.0-r2 p3) gcc-trunk too $ gcc -Wall -Wextra -O3 test.c $ ./a.out Abort */ #define BIG_ENDIAN __attribute__((scalar_storage_order("big-endian"))) /* host order version (little endian)*/ struct _ip6_addr { union { char addr8[16]; int addr32[4]; } u; }; typedef struct _ip6_addr t_ip6_addr; struct _net_addr { char is_v4; union { intaddr; t_ip6_addr addr6; } u; }; typedef struct _net_addr t_net_addr; /* big endian version */ struct _be_ip6_addr { union { char addr8[16]; } BIG_ENDIAN u; } BIG_ENDIAN; typedef struct _be_ip6_addr t_be_ip6_addr; struct _be_net_addr { char is_v4; union { t_be_ip6_addr addr6; int addr; } BIG_ENDIAN u; } BIG_ENDIAN; typedef struct _be_net_addr t_be_net_addr; /* convert */ t_be_ip6_addr be_ip6_addr(const t_ip6_addr ip6) { t_be_ip6_addr rc = { .u.addr8[0] = ip6.u.addr8[0], .u.addr8[1] = ip6.u.addr8[1], .u.addr8[2] = ip6.u.addr8[2], .u.addr8[3] = ip6.u.addr8[3], .u.addr8[4] = ip6.u.addr8[4], .u.addr8[5] = ip6.u.addr8[5], .u.addr8[6] = ip6.u.addr8[6], .u.addr8[7] = ip6.u.addr8[7], .u.addr8[8] = ip6.u.addr8[8], .u.addr8[9] = ip6.u.addr8[9], .u.addr8[10] = ip6.u.addr8[10], .u.addr8[11] = ip6.u.addr8[11], .u.addr8[12] = ip6.u.addr8[12], .u.addr8[13] = ip6.u.addr8[13], .u.addr8[14] = ip6.u.addr8[14], .u.addr8[15] = ip6.u.addr8[15], }; return rc; } t_be_net_addr be_net_addr(const t_net_addr ip) { t_be_net_addr rc = {.is_v4 = ip.is_v4 }; if (ip.is_v4) { rc.u.addr = ip.u.addr; } else { rc.u.addr6 = be_ip6_addr(ip.u.addr6); } return rc; } int main(void) { t_be_net_addr out = { }; t_net_addr in = { .is_v4 = 0, .u.addr6.u.addr8 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }; out = be_net_addr(in); // actually first 4 bytes are swapped if (in.u.addr6.u.addr8[0] != out.u.addr6.u.addr8[0]) __builtin_abort(); return 0; }
[Bug c/118836] New: sso warning dependend on -fno-builtin
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118836 Bug ID: 118836 Summary: sso warning dependend on -fno-builtin Product: gcc Version: 14.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: george.thopas at gmail dot com Target Milestone: --- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100920 introduced some logic to suppress scalar-storage-order warnings when using memcpy/memset/... However when required to compile with -fno-builtin this won't work and will still gives scalar-storage-order warnings Thank you. example : compiling gcc/testsuite/ gcc.dg/sso-14.c bash$ gcc -Wall -fno-builtin sso-14.c sso-14.c: In function 'main': sso-14.c:51:11: warning: passing argument 1 of 'memset' from incompatible scalar storage order [-Wscalar-storage-order] 51 | memset (msg1, 0, sizeof (t_s12)); | ^~~~ sso-14.c:52:11: warning: passing argument 1 of 'memcpy' from incompatible scalar storage order [-Wscalar-storage-order] 52 | memcpy (msg2, &msg1, sizeof (t_s12)); | ^~~~ sso-14.c:53:18: warning: passing argument 1 of 'memcmp' from incompatible scalar storage order [-Wscalar-storage-order] 53 | same = memcmp (msg1, msg2, sizeof (t_s12)); | ^~~~ sso-14.c:53:24: warning: passing argument 2 of 'memcmp' from incompatible scalar storage order [-Wscalar-storage-order] 53 | same = memcmp (msg1, msg2, sizeof (t_s12)); |^~~~ sso-14.c:46:7: warning: variable 'same' set but not used [-Wunused-but-set-variable] 46 | int same;
[Bug c/118836] sso warning dependend on -fno-builtin
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118836 --- Comment #2 from George Thopas --- (In reply to Andrew Pinski from comment #1) > This is by design; without -fno-builtin, memcmp, memset, etc. become normal > functions and they have unknown behaviors. The only solution to get rid of the warning is to explicit cast each argument every where it's called. This makes for far worse code as you lose the validation that the argument are pointers I really do not want to disable the sso warning globally either as it's an umbrella for a set of warning. I do not want disable sso punning errors for example which point to real problems. Pragma's are also of no help as you can't disable the warning on a function level, so you would have to put pragma's around each call While it may be as designed, there is at least an inconsistency here. And it still is not clear how any of these type warnings bring anything to the table for void pointers. Can you suggest any path forward ? Thanks