[Bug c++/115291] armv8-a GCC emits float32x2_t loads from uninitialized stack

2024-05-31 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115291

--- Comment #3 from Akihiko Odaki  ---
You are right. Sorry for bothering and thanks for pointing out the issue in the
code (and even the relevant documentation!)

[Bug c++/115291] New: armv8-a GCC emits float32x2_t loads from uninitialized stack

2024-05-30 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115291

Bug ID: 115291
   Summary: armv8-a GCC emits float32x2_t loads from uninitialized
stack
   Product: gcc
   Version: 14.1.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: akihiko.odaki at daynix dot com
  Target Milestone: ---

Run the following commands:
git clone https://gitlab.com/libeigen/eigen.git -b
38b9cc263bbaeb03ce408a4e26084543a6c0dedb
cat main.cpp <<'EOF'
#include "Eigen/Core"

auto f() -> Eigen::Matrix2f {
  return Eigen::Matrix2f::Zero();
}

auto g() -> Eigen::Vector2f {
  auto v = Eigen::Product(f(), Eigen::Vector2f::Zero());
  return v;
}
EOF

c++ -Ieigen -O1 -DNDEBUG main.cpp -S

Now main.s looks like:
.arch armv8-a
.file   "main.cpp"
.text
.align  2
.global _Z1fv
.type   _Z1fv, %function
_Z1fv:
.LFB13241:
.cfi_startproc
mov x0, x8
str wzr, [x8]
str wzr, [x8, 4]
str wzr, [x8, 8]
str wzr, [x8, 12]
ret
.cfi_endproc
.LFE13241:
.size   _Z1fv, .-_Z1fv
.align  2
.global _Z1gv
.type   _Z1gv, %function
_Z1gv:
.LFB13246:
.cfi_startproc
sub sp, sp, #16
.cfi_def_cfa_offset 16
mov x0, x8
moviv30.2s, 0
ldr d31, [sp]
fmulv31.2s, v31.2s, v30.2s
ldr d29, [sp, 8]
fmlav31.2s, v29.2s, v30.2s
str d31, [x8]
add sp, sp, 16
.cfi_def_cfa_offset 0
ret
.cfi_endproc
.LFE13246:
.size   _Z1gv, .-_Z1gv
.align  2
.type   _GLOBAL__sub_I__Z1fv, %function
_GLOBAL__sub_I__Z1fv:
.LFB14439:
.cfi_startproc
ret
.cfi_endproc
.LFE14439:
.size   _GLOBAL__sub_I__Z1fv, .-_GLOBAL__sub_I__Z1fv
.ident  "GCC: (GNU) 14.1.1 20240507 (Red Hat 14.1.1-1)"
.section.note.GNU-stack,"",@progbits

In _Z1gv, "ldr  d31, [sp]" loads values from nowhere.

[Bug sanitizer/114494] false-positive with -O2 -Wstringop-overflow=2 -fsanitize=address

2024-04-02 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114494

--- Comment #6 from Akihiko Odaki  ---
(In reply to Hans-Peter Nilsson from comment #5)
> (In reply to Akihiko Odaki from comment #0)
> > if (hlen < sizeof(struct ip_header)) {
> 
> Is this a typo for "if (hlen > sizeof(struct ip_header)) {" which makes a
> bot more sense to me?
> 
> (I can't find it in Linux/drivers, so can't check "upstream" status.)

It is not Linux but QEMU. Please look at:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114494#c0

[Bug sanitizer/114494] false-positive with -O2 -Wstringop-overflow=2 -fsanitize=address

2024-03-26 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114494

--- Comment #3 from Akihiko Odaki  ---
(In reply to Andrew Pinski from comment #2)
> Note the minimized testcase seems to be a real issue. hlen can either be 1
> (the only value that works) or more than 1.

Below is the the error message for the minimized testcase:

: In function 'rtl8139_cplus_transmit_one':
:23:5: warning: writing 1 byte into a region of size 0
[-Wstringop-overflow=]
:4:11: note: at offset 1 into destination object 'ip_ver_len' of size 1

It does not seem to care if hlen == 1 or not.

[Bug sanitizer/114494] New: false-positive with -O2 -Wstringop-overflow=2 -fsanitize=address

2024-03-26 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114494

Bug ID: 114494
   Summary: false-positive with -O2 -Wstringop-overflow=2
-fsanitize=address
   Product: gcc
   Version: 13.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: sanitizer
  Assignee: unassigned at gcc dot gnu.org
  Reporter: akihiko.odaki at daynix dot com
CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
jakub at gcc dot gnu.org, kcc at gcc dot gnu.org
  Target Milestone: ---

Building
https://gitlab.com/qemu-project/qemu/-/commits/v9.0.0-rc1?ref_type=tags causes
the following warning:

cc -m64 -mcx16 -Ilibcommon.fa.p -Isubprojects/dtc/libfdt
-I../subprojects/dtc/libfdt -I/usr/include/glib-2.0
-I/usr/lib64/glib-2.0/include -I/usr/include/libmount -I/usr/include/blkid
-I/usr/include/sysprof-6 -I/usr/include/gio-unix-2.0 -fdiagnostics-color=auto
-Wall -Winvalid-pch -Werror -std=gnu11 -O2 -g -fsanitize=address
-fstack-protector-strong -Wempty-body -Wendif-labels -Wexpansion-to-defined
-Wformat-security -Wformat-y2k -Wignored-qualifiers -Wimplicit-fallthrough=2
-Winit-self -Wmissing-format-attribute -Wmissing-prototypes -Wnested-externs
-Wold-style-declaration -Wold-style-definition -Wredundant-decls -Wshadow=local
-Wstrict-prototypes -Wtype-limits -Wundef -Wvla -Wwrite-strings
-Wno-missing-include-dirs -Wno-psabi -Wno-shift-negative-value -isystem
/home/me/qemu/linux-headers -isystem linux-headers -iquote . -iquote
/home/me/qemu -iquote /home/me/qemu/include -iquote
/home/me/qemu/host/include/x86_64 -iquote /home/me/qemu/host/include/generic
-iquote /home/me/qemu/tcg/i386 -pthread -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
-D_LARGEFILE_SOURCE -fno-strict-aliasing -fno-common -fwrapv
-ftrivial-auto-var-init=zero -fzero-call-used-regs=used-gpr -fPIE -MD -MQ
libcommon.fa.p/hw_net_rtl8139.c.o -MF libcommon.fa.p/hw_net_rtl8139.c.o.d -o
libcommon.fa.p/hw_net_rtl8139.c.o -c ../hw/net/rtl8139.c
../hw/net/rtl8139.c: In function 'rtl8139_io_writeb':
../hw/net/rtl8139.c:2273:17: error: writing 8 bytes into a region of size 0
[-Werror=stringop-overflow=]
 2273 | memcpy(data_to_checksum, saved_ip_header + 12, 8);

Below is a minimized reproduction case:
gcc -O2 -Wstringop-overflow=2 -fsanitize=address -c -x c - <

struct ip_header {
char  ip_ver_len;
};

void rtl8139_cplus_transmit_one(char *saved_buffer)
{
struct ip_header *ip;
int hlen;

char *eth_payload_data = saved_buffer + 4;

ip = (struct ip_header*)eth_payload_data;

hlen = ip->ip_ver_len;
if (hlen < sizeof(struct ip_header)) {
return;
}

char saved_ip_header[1];
memcpy(saved_ip_header, eth_payload_data, hlen);
memcpy(eth_payload_data + hlen, saved_ip_header, 1);
}
EOF

[Bug sanitizer/114217] -fsanitize=alignment false positive with intended unaligned struct member access

2024-03-04 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114217

--- Comment #13 from Akihiko Odaki  ---
(In reply to Jakub Jelinek from comment #12)
> (In reply to Akihiko Odaki from comment #11)
> > So there are two constructs invoking UBs but ignored by UBSan: 1)
> 
> That is an understatement. UBSan is a best effort which diagnoses some forms
> of undefined behavior.  There are tons of undefined behavior UBSan doesn't
> catch,
> most importantly e.g. aliasing violations, but far from limited to just that.
> If a program is diagnostic free with -fsanitize=undefined,address , it
> doesn't mean it is UB free, but the goal is that if there is diagnostic,
> there is a real UB in the program.

Right. I just listed the two relevant constructs and don't intend to say they
are the only case that UBSan doesn't catch.

> 
> You are basically asking for the PR80797 fix to be reverted just because you
> aren't willing to fix UB in your code.  That is not going to happen, we've
> been diagnosing this for almost 7 years now, I think clang even for 11
> years, it is a real UB and other projects have been able to cope with it. 
> By reverting the change new UB in other programs couldn't be discovered.

I'm not asking for reverting PR80797. See f() and f2() I wrote earlier:
u64 f(struct dir_entry *entry)
{
return get_unaligned(&entry->offset);
}

u64 f2(u64 *offset)
{
return get_unaligned(offset);
}

Both f(NULL) and f2(NULL) should be caught and there should be no discrepancy
in behavior for these two functions. However, there is a discrepancy when it
comes to -fsanitize=alignment.

I'm not saying ignoring UB in f() is the only sensible option either. Catching
UBs in both f() and f2() is a logical option.

[Bug sanitizer/114217] -fsanitize=alignment false positive with intended unaligned struct member access

2024-03-04 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114217

--- Comment #11 from Akihiko Odaki  ---
(In reply to Jakub Jelinek from comment #9)
> (In reply to Akihiko Odaki from comment #8)
> > It would certainly workaround the issue, but it's only dirtier and brings no
> > benefit except suppressed UBSan errors. Why not allow
> > get_unaligned(&entry->offset) when UBSan does not complain about that hack?
> 
> The purpose of the sanitizer is to find undefined behavior, and it found one.
> If you don't want it to find undefined behavior, don't use it.
> 
> > > If you want something that will be valid even in C, don't pass struct
> > > dir_entry *entry
> > > argument, but void *entry instead, and use e.g.
> > > __get_unaligned_t(__typeof(((struct dir_entry *)0)->offset), ((char
> > > *)entry)+offsetof(struct dir_entry, offset)))
> > > You can surely hide that all under some macro.
> > 
> > The definition still involves UB for ((struct dir_entry *)0)->offset.
> > Perhaps __typeof() may be considered as an exception, but what if offsetof()
> > is defined as follows?
> > 
> > #define offsetof(T, x) ((uintptr_t)&(((T *)0)->x))
> 
> typeof nor sizeof operators don't evaluate their arguments unless the
> expressions have VLA type.  So, if there would be undefined behavior if they
> were evaluated, it doesn't matter because they aren't.  So, e.g.
> 
> void
> foo (int n, int *p)
> {
>   typedef int A[n];
>   A b[4];
>   typedef int C[10];
>   C d[4];
>   int i = 0;
>   int j = 0;
>   typeof (b[++i]) e;
>   typeof (d[++j]) f;
>   typeof (d[100][4]) g;
>   p[0] = i;
>   p[1] = j;
> }
> 
> doesn't invoke undefined behavior and sets p[0] to 1 and p[1] to 0, b[++i]
> had VLA type, so it got evaluated, the other 2 didn't, so ++j wasn't
> evaluated and the d[100]
> UB wasn't triggered, as if the program did if (n == 54) d[100][4]; and n at
> runtime was
> never 54.  __typeof is a GNU extension but behaves the same way.
> 
> offsetof is a standard C macro.  It is not defined in the standard as
> dereferencing NULL pointer, but as if there was an object of the T type and
> it computed the difference between the address of the x member of it and the
> start of the object.
> If offsetof is defined as
> #define offsetof(T, x) ((size_t)(uintptr_t)&(((T *)0)->x))
> by the implementation (and yes, e.g. GCC < 4 used to define it similarly),
> then obviously the compiler can't assume there is undefined behavior on such
> expressions,
> but it didn't at that point, there was no UBSAN, such expressions evaluated
> to a constant expression early before anything could have considered there
> might be UB and after it was just the resulting constant.
> If the implementation doesn't have some exception that considers expressions
> like
> &(((T *)0)->x) valid, then it can't use such offsetof definition and needs
> to use something else, like GCC uses __builtin_offsetof.  That said, GCC
> AFAIK still treats expressions like the above as offsetof-like (because
> there has been a lot of such code in the wild for decades), folds them to
> constant right away and doesn't complain about it with ubsan; clang does
> complain about it though and doesn't treat it that way.
> Anyway, if you use something like ((size_t)(uintptr_t)&(((T *)0)->x)), per C
> rules you are invoking UB, while if you use offsetof(T, x), it is well
> defined.

So there are two constructs invoking UBs but ignored by UBSan: 1) construction
of misaligned pointers that do not involve a struct member, and 2) pointer
arithmetic with a member of an invalid struct pointer as done by old
offsetof().

If UBSan catches get_unaligned(&entry->offset), why not catch those constructs
too? Perhaps 2) may not be relevant for UBSan since it's done at compile time,
but 1) is.

Whether 1) should be caught is a more complicated question. From a certain
viewpoint, it should be caught since it's UB, and future GCC and other
compilers may introduce incompatible optimization; there will be real bugs if
that happens.

On the other hand, the current GCC does not perform such an optimization, and
clang does not either at least when a packed struct is used or
__builtin_memcpy() is used and its argument is casted to void * or char *
(c.f., https://github.com/llvm/llvm-project/issues/83710). In that sense,
catching 1) brings only noises.

In any case, the answer to the question of whether 1) should be caught should
not be different from whether get_unaligned(&entry->offset) should be caught.

[Bug sanitizer/114217] -fsanitize=alignment false positive with intended unaligned struct member access

2024-03-03 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114217

--- Comment #8 from Akihiko Odaki  ---
(In reply to Jakub Jelinek from comment #7)
> GCC actually doesn't diagnose on mere pointer assignment, but what triggers
> the alignment check is
> &entry->offset
> even when the code later on just takes its address, entry must be
> sufficiently aligned, otherwise entry->offset is invalid.
> Under standard C rules, already forming the pointer would be UB, so
> somewhere in the caller when you prepare what to pass to the f function.
> 
> If you want something that will still be invalid C,
> but will not trigger UBSAN errors, then e.g.
> unsigned long long h(struct dir_entry *entry)
> {
> return get_unaligned((unsigned long long *) (((char *) entry) + offsetof
> (struct dir_entry, offset)));
> }
> will do.

It would certainly workaround the issue, but it's only dirtier and brings no
benefit except suppressed UBSan errors. Why not allow
get_unaligned(&entry->offset) when UBSan does not complain about that hack?

> If you want something that will be valid even in C, don't pass struct
> dir_entry *entry
> argument, but void *entry instead, and use e.g.
> __get_unaligned_t(__typeof(((struct dir_entry *)0)->offset), ((char
> *)entry)+offsetof(struct dir_entry, offset)))
> You can surely hide that all under some macro.

The definition still involves UB for ((struct dir_entry *)0)->offset. Perhaps
__typeof() may be considered as an exception, but what if offsetof() is defined
as follows?

#define offsetof(T, x) ((uintptr_t)&(((T *)0)->x))

GCC does provide __builtin_offsetof(), but I think definitions of offsetof()
like this are still prevalent, and expected to work although it's UB. If GCC
tolerates this kind of trick, why not tolerate get_unaligned(&entry->offset)?

[Bug sanitizer/114217] -fsanitize=alignment false positive with intended unaligned struct member access

2024-03-02 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114217

--- Comment #6 from Akihiko Odaki  ---
(In reply to Andrew Pinski from comment #4)
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/
> include/asm-generic/unaligned.h?h=v6.7
> 
> is correct except it should not expose get_unaligned/put_unaligned since the
> undefined code happens way before.
> 
> The problem is with the btrfs code in btrfs_filldir:
> ```
> static int btrfs_filldir(void *addr, int entries, struct dir_context *ctx)
> {
>   while (entries--) {
>   struct dir_entry *entry = addr; /// THIS IS BROKEN and causes 
> the
> -fsanitize=alignment error
>   char *name = (char *)(entry + 1);
> 
>   ctx->pos = get_unaligned(&entry->offset);
>   if (!dir_emit(ctx, name, get_unaligned(&entry->name_len),
>get_unaligned(&entry->ino),
>get_unaligned(&entry->type)))
>   return 1;
>   addr += sizeof(struct dir_entry) +
>   get_unaligned(&entry->name_len);
>   ctx->pos++;
>   }
>   return 0;
> }
> ```
> 
> Added comment on where the error comes from. The get_unaligned macro really
> should not be used here. What should be used here is an unaligned version of
> `struct dir_entry` instead.

With looking at this comment, I did another experiment to see if it's specific
to struct members, 
Also, note that this behavior of UBSan is specific to struct members. Think of
the following functions:

u64 f2(u64 *offset)
{
return get_unaligned(offset);
}

u64 g2(u64 *offset)
{
return *offset;
}

f2() and g2() correspond to f() and g(). The only difference is that it does
not involve struct member access. Nevertheless, GCC changes its behavior and
doesn't emit alignment checks for f2().

If casting a pointer with a strict alignment requirement to one with a relaxed
alignment requirement doesn't relax the alignment requirement, UBSan should
emit an error for f2().

[Bug sanitizer/114217] -fsanitize=alignment false positive with intended unaligned struct member access

2024-03-02 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114217

--- Comment #5 from Akihiko Odaki  ---
(In reply to Andrew Pinski from comment #4)
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/
> include/asm-generic/unaligned.h?h=v6.7
> 
> is correct except it should not expose get_unaligned/put_unaligned since the
> undefined code happens way before.
> 
> The problem is with the btrfs code in btrfs_filldir:
> ```
> static int btrfs_filldir(void *addr, int entries, struct dir_context *ctx)
> {
>   while (entries--) {
>   struct dir_entry *entry = addr; /// THIS IS BROKEN and causes 
> the
> -fsanitize=alignment error
>   char *name = (char *)(entry + 1);
> 
>   ctx->pos = get_unaligned(&entry->offset);
>   if (!dir_emit(ctx, name, get_unaligned(&entry->name_len),
>get_unaligned(&entry->ino),
>get_unaligned(&entry->type)))
>   return 1;
>   addr += sizeof(struct dir_entry) +
>   get_unaligned(&entry->name_len);
>   ctx->pos++;
>   }
>   return 0;
> }
> ```
> 
> Added comment on where the error comes from. The get_unaligned macro really
> should not be used here. What should be used here is an unaligned version of
> `struct dir_entry` instead.

I understand the idea. What I don't get is that GCC still emits code for
unaligned memory access in such a case. It is just a waste of performance if
GCC doesn't provide a guarantee that the unaligned access is performed in such
a case and is not optimal.

[Bug sanitizer/114217] -fsanitize=alignment false positive with intended unaligned struct member access

2024-03-02 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114217

--- Comment #3 from Akihiko Odaki  ---
(In reply to Andrew Pinski from comment #1)
> >but also emits code to assert alignment.
> 
> 
> Yes because the code is broken still.
> 
> The alignment is not about when the access happens but rather when the
> pointer is casted to.
> 
> So in this case when passing in the argument to f, the argument entry should
> be aligned to what the `struct dir_entry` is aligned to; otherwise it is
> undefined code.


I had a similar thought when I faced the same issue before and didn't report it
then, but this time I realized GCC still emits code to perform slow unaligned
access for such a construct. Whichever is right, to assume an aligned or
unaligned access, it is not consistent.

Theoretically, it also makes sense to emit unaligned memory access for such a
construct instead of ignoring it when -fsanitize=address, but I'm worried that
such a change will break too many things.

[Bug sanitizer/114217] New: -fsanitize=alignment false positive with intended unaligned struct member access

2024-03-02 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114217

Bug ID: 114217
   Summary: -fsanitize=alignment false positive with intended
unaligned struct member access
   Product: gcc
   Version: 13.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: sanitizer
  Assignee: unassigned at gcc dot gnu.org
  Reporter: akihiko.odaki at daynix dot com
CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
jakub at gcc dot gnu.org, kcc at gcc dot gnu.org
  Target Milestone: ---

-fsanitize=alignment generates a false positive error for an intended unaligned
struct member access. The intention of unaligned struct member access is
expressed with __builtin_memcpy() as done by QEMU or packed struct access as
done by Linux. GCC translates such a construct to code to access memory
unaligned for architectures like rv64gc as intended but also emits code to
enforce the alignment.

The relevant code of QEMU is at:
https://gitlab.com/qemu-project/qemu/-/blob/v8.2.1/include/qemu/bswap.h?ref_type=tags
The relevant code of Linux is at:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/unaligned.h?h=v6.7

FYI, this issue is reproducible also with clang 17.0.1, and I'm going to open
an issue for it, too.

To reproduce the issue, compile the code shown below with -O2
-fsanitize=alignment for rv64gc:

#include 

typedef uint64_t u64;

/*
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/compiler_attributes.h?h=v6.7
*/

/*
 *   gcc:
https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute
 * clang:
https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
 */
#define __packed__attribute__((__packed__))

/*
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/unaligned.h?h=v6.7
*/

#define __get_unaligned_t(type, ptr) ({
\
const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); 
\
__pptr->x; 
\
})

#define __put_unaligned_t(type, val, ptr) do { 
\
struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr);   
\
__pptr->x = (val); 
\
} while (0)

#define get_unaligned(ptr)  __get_unaligned_t(typeof(*(ptr)), (ptr))
#define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr))

/*
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/btrfs/inode.c?h=v6.7
*/

struct dir_entry {
u64 ino;
u64 offset;
unsigned type;
int name_len;
};

/*
 * This function is intended to perform an unaligned access.
 * GCC emits code for an unaligned operation as intended,
 * but also emits code to assert alignment.
 */
u64 f(struct dir_entry *entry)
{
return get_unaligned(&entry->offset);
}

/*
 * This function is intended to perform an aligned access.
 * GCC emits code for an aligned operation,
 * and emits code to assert alignment.
 */
u64 g(struct dir_entry *entry)
{
return entry->offset;
}

[Bug tree-optimization/109002] -O1 -ftree-pre -ftree-partial-pre results in stall value

2023-03-02 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109002

--- Comment #2 from Akihiko Odaki  ---
Oops. Replacing i++ with i = !i removes the undefined behavior while the bug
still remains.

[Bug tree-optimization/109002] New: -O1 -ftree-pre -ftree-partial-pre results in stall value

2023-03-02 Thread akihiko.odaki at daynix dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109002

Bug ID: 109002
   Summary: -O1 -ftree-pre -ftree-partial-pre results in stall
value
   Product: gcc
   Version: 13.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: tree-optimization
  Assignee: unassigned at gcc dot gnu.org
  Reporter: akihiko.odaki at daynix dot com
  Target Milestone: ---

The following should emit an executable which prints "a" forever, but the
actual compiled executable prints nothing and just hangs. It seems the code
sees a stall value of variable g.

gcc -O1 -ftree-pre -ftree-partial-pre -x c - <

int g;
int h;

int main(void)
{
for (int i = 0; ; i++) {
for (int j = 0; j < g; j++);

if (i & 1) {
if (h)
continue;

if (g)
puts("a");

g = 1;
}
}
}
EOF

I reproduced this bug with the current master. gcc -v says:
Using built-in specs.
COLLECT_GCC=/home/alarm/gcc-installation/usr/local/bin/gcc
COLLECT_LTO_WRAPPER=/home/alarm/gcc-installation/usr/local/bin/../libexec/gcc/aarch64-unknown-linux-gnu/13.0.1/lto-wrapper
Target: aarch64-unknown-linux-gnu
Configured with: ../gcc/configure --disable-bootstrap : (reconfigured)
../gcc/configure --disable-bootstrap
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.0.1 20230302 (experimental) (GCC) 
COLLECT_GCC_OPTIONS='-v' '-mlittle-endian' '-mabi=lp64'

/home/alarm/gcc-installation/usr/local/bin/../libexec/gcc/aarch64-unknown-linux-gnu/13.0.1/cc1
-quiet -v -iprefix
/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/
/home/alarm/a.c -quiet -dumpbase a.c -dumpbase-ext .c -mlittle-endian
-mabi=lp64 -version -o /tmp/ccetU9yt.s
GNU C17 (GCC) version 13.0.1 20230302 (experimental)
(aarch64-unknown-linux-gnu)
compiled by GNU C version 12.1.0, GMP version 6.2.1, MPFR version
4.2.0, MPC version 1.3.1, isl version isl-0.25-GMP

GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
ignoring nonexistent directory
"/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/../../../../aarch64-unknown-linux-gnu/include"
ignoring duplicate directory
"/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/../../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/include"
ignoring duplicate directory
"/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/../../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/include-fixed"
ignoring nonexistent directory
"/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/../../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/../../../../aarch64-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:

/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/include

/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/include-fixed
 /usr/local/include
 /usr/include
End of search list.
Compiler executable checksum: 374b2759695ed1b72f52cb0f1847fbb3
COLLECT_GCC_OPTIONS='-v' '-mlittle-endian' '-mabi=lp64'
 as -v -EL -mabi=lp64 -o /tmp/ccTu98hj.o /tmp/ccetU9yt.s
GNU assembler version 2.38 (aarch64-unknown-linux-gnu) using BFD version (GNU
Binutils) 2.38
COMPILER_PATH=/home/alarm/gcc-installation/usr/local/bin/../libexec/gcc/aarch64-unknown-linux-gnu/13.0.1/:/home/alarm/gcc-installation/usr/local/bin/../libexec/gcc/
LIBRARY_PATH=/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/:/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/:/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/../../../../lib64/:/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-mlittle-endian' '-mabi=lp64' '-dumpdir' 'a.'

/home/alarm/gcc-installation/usr/local/bin/../libexec/gcc/aarch64-unknown-linux-gnu/13.0.1/collect2
-plugin
/home/alarm/gcc-installation/usr/local/bin/../libexec/gcc/aarch64-unknown-linux-gnu/13.0.1/liblto_plugin.so
-plugin-opt=/home/alarm/gcc-installation/usr/local/bin/../libexec/gcc/aarch64-unknown-linux-gnu/13.0.1/lto-wrapper
-plugin-opt=-fresolution=/tmp/ccup8iGA.res -plugin-opt=-pass-through=-lgcc
-plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s
--eh-frame-hdr -dynamic-linker /lib/ld-linux-aarch64.so.1 -X -EL -maarch64linux
/lib/crt1.o /lib/crti.o
/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/aarch64-unknown-linux-gnu/13.0.1/crtbegin.o
-L/home/alarm/gcc-installation/usr/local/bin/../lib/gcc/aarch64-unknown-linux-gnu/13.0.1
-L/home/alarm/gcc-installation/usr/local/bin/../lib/gcc
-L/home/alarm/gcc-installation/usr/local/bin/../