[Bug middle-end/61577] [4.9.0 Regression] can't compile on hp-ux v3 ia64

2021-04-24 Thread peter at int19h dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61577

--- Comment #214 from Peter Bisroev  ---
(In reply to Andrew Pinski from comment #213)
> Does this still happen with GCC 8 or above?

Hi Andrew, yes it does from my last tests. As we have found out here, before
newer versions of GCC can work on HP-UX we need to get a working gas. Please
refer to this gas Bugzilla ticket for details:

https://sourceware.org/bugzilla/show_bug.cgi?id=25599

[Bug c++/97976] Optimization relating to NULL pointer assumptions in gcc 9.1

2020-11-25 Thread peter at int19h dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97976

--- Comment #10 from Peter Bisroev  ---
Jonathan, thank you so much for your explanation. As soon as I read it, it all
started to make sense.

>You cannot increment or decrement a pointer past the end of an array (except 
>the one past the end position).

Yes of course, that is perfectly reasonable. And unless I am mistaken, the
examples that I have provided do not do that directly because as the "array" in
those examples starts at address 0 as can be possible in some embedded systems.
But with the knowledge about how by default gcc treats a pointer to address 0
everything can be perfectly explained.

>GCC assumes there is no object at address zero, see the documentation for 
>-fdelete-null-pointer-checks

Thank you for pointing this flag out to me. After reading its description and
searching a bit I can see that I am not the only one that got caught off guard
with this as shown in these links:

* https://gcc.gnu.org/legacy-ml/gcc-patches/2015-04/msg00790.html
* https://gcc.gnu.org/legacy-ml/gcc-patches/2007-03/msg01968.html
* https://lkml.org/lkml/2018/4/4/601
* https://reviews.llvm.org/D47894

I will definitely go through gcc man page again to see if there is anything
else that we should pay attention to.

Once again, thank you for taking the time to explain all of this!

[Bug c++/97976] Optimization relating to NULL pointer assumptions in gcc 9.1

2020-11-25 Thread peter at int19h dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97976

--- Comment #7 from Peter Bisroev  ---
Thank you for your response Jonathan.

If you have a minute, could you please clarify a few things. I have been
talking about this behavior with a few colleagues and we are all slightly
confused by the same issue. So I think the answers here can definitely help a
few people besides myself.

>It is undefined to decrement a pointer "before" the start of an object

I am sorry, but I am not sure where I am doing this? For example, lets say I am
accessing raw memory on an embedded system and I have bytes 0, 1, 1, 1 at
addresses 0, 1, 2 and 3 respectively. I know this is a trivial example and
makes no sense on x86 arch (almost, in real mode maybe). So if I call
containsBackwardsSafe(p, 2) with p == 3, shouldn't I get back -1? I guess it
all depends on what is the "object" in this context. Conceivably some other
function could have mapped that memory at that address on that system and
passed the pointer to containsBackwardsSafe() function. In that case wouldn't
the responsibility of "object" be up to the system and not the compiler?

I have also just tried going through C11 draft
(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) to try to find
relevant standard sections that would describe this behavior. I have read
through sections:
* 6.2.5 Types (specifically paragraphs 14 and 20)
* 6.3.2.3 Pointers
* 6.5.3.1 Prefix increment and decrement operators
* 6.5.6 Additive operators (specifically paragraphs 7, 8 and 9)
* 6.5.16.2 Compound assignment

And I cannot seem to find relevant information that forbids pointer decrement
as  shown in containsBackwardsSafe() or containsBackwards() from the last
comment. If you could point me to the right section of the standard it would be
incredibly helpful. I am sure I must be missing something obvious.

Once again, thank you for your time and help on this.

Regards,
--peter

[Bug c++/97976] Optimization relating to NULL pointer assumptions in gcc 9.1

2020-11-25 Thread peter at int19h dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97976

Peter Bisroev  changed:

   What|Removed |Added

 Resolution|INVALID |FIXED

--- Comment #5 from Peter Bisroev  ---
Thank you for your explanation Richard, it makes perfect sense to me now. GCC
is being insanely clever here!

However I still think there is something not 100% right. If I change
containsBackwards() function to look like this:


int containsBackwards(const uint8_t* p, uint8_t target)
{
for (;;)
{
if (*p == target)
{
return 1;
}

--p;
if (!p)
{
return 0;
}
}
}


I apologize in advance as I know the code is far from ideal and is definitely a
corner case, but unless I am mistaken there is no undefined behavior here
assuming p is always valid at the time of the call and it is just to illustrate
the example. So for the above gcc 10.1 generates the following:



containsBackwards(unsigned char const*, unsigned char):
mov eax, 1
ret


So my question is, is gcc allowed to assume that the target will always match?

Additionally, if I make this function a bit safer and unless I am mistaken
without any undefined behavior:


int containsBackwardsSafe(const uint8_t* p, uint8_t target)
{
if (!p)
{
return 0;
}

for (;;)
{
if (*p == target)
{
return 1;
}

--p;
if (!p)
{
return -1;
}
}
}


Then gcc 10.1 generates the following:


containsBackwardsSafe(unsigned char const*, unsigned char):
xor eax, eax
testrdi, rdi
setne   al
ret


Which matches the generated output of the original function. However unless I
am mistaken the result here is supposed to be different to the original
function:
* If p == NULL, return 0.
* If target matched while p was valid, return 1.
* If target did not match while p was valid return -1.

You can see these above examples at Compiler Explorer here:

https://godbolt.org/z/ha1c1h


I apologize if there is something critical I am missing here so I hope I am not
wasting your time.

Thank you!
--peter

[Bug c++/97976] Optimization regression in 10.1 for lambda passed as template argument

2020-11-24 Thread peter at int19h dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97976

Peter Bisroev  changed:

   What|Removed |Added

 Resolution|INVALID |---
 Status|RESOLVED|UNCONFIRMED

--- Comment #3 from Peter Bisroev  ---
Hi Andrew,

I was thinking about this a bit more and decided to try the loop in reverse in
a more simplified test case. I know this test case demonstrates a corner case
that no one will probably implement. However I still think it merits some
further investigation just in case this affects some other parts of the
optimizer. You can see this code below:


int containsBackwards(const uint8_t* p, uint8_t target)
{
for (; p; --p)
{
if (*p == target)
{
return 1;
}
}
return 0;
}

const uint8_t* findBackwards(const uint8_t* p, uint8_t target)
{
for (; p; --p)
{
if (*p == target)
{
break;
}
}
return p;
}



Function containsBackwards(), while searching backwards, should return 1 if
target byte is found and 0 if it was not and p points to address 0. Function
findBackwards() is similar but returns the address of the first byte that
matched the target or pointer to address 0 if a match was not found. Unless I
am mistaken, the sample code above is not hitting any undefined behavior such
as dereferencing a NULL pointer and there is a well defined loop terminating
condition.

This is the code that is generated with gcc trunk and gcc 9.1:

containsBackwards(unsigned char const*, unsigned char):
xor eax, eax
testrdi, rdi
setne   al
ret
findBackwards(unsigned char const*, unsigned char):
testrdi, rdi
jne .L5
jmp .L6
.L8:
sub rdi, 1
.L5:
cmp BYTE PTR [rdi], sil
jne .L8
mov rax, rdi
ret
.L6:
xor eax, eax
ret


I would have expected both functions to be compiled to nearly the same code,
but the looping is missing in containsBackwards() function. And unless I am
mistaken gcc 8.3 generates the output that we would expect to see here.

You can see this example in Compiler Explorer here:

https://godbolt.org/z/hWE4xs

What is also interesting, if we replace uint8_t by uint32_t in
containsBackwards() function it will work with gcc 9.3 but with gcc 10.1 it
will behave in exactly the same way as above returning the result based on the
validity of the p pointer.

Additionally, thinking about my first test case. I know it was technically in
the undefined territory, but just for my personal understanding, is the
compiler allowed to assume that pi can never become null like you have
suggested? In theory it can overflow and become 0 and the loop will terminate
but unfortunately I am not 100% certain of what the standard's view on this is.
In addition, can the compiler assume that callback(*pi) will never return true?

What are your thoughts?

Thank you!
--peter

[Bug c++/97976] Optimization regression in 10.1 for lambda passed as template argument

2020-11-24 Thread peter at int19h dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97976

Peter Bisroev  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |INVALID

--- Comment #2 from Peter Bisroev  ---
Hi Andrew,

You are 100% correct. I realized that as soon as I hit submit button. I was
trying to create a simple test case of the problem that I saw and a bit
oversimplified it. GCC actually optimized this really well.

I apologize for a false report.

Regards,
--peter

[Bug c++/97976] New: Optimization regression in 10.1 for lambda passed as template argument

2020-11-24 Thread peter at int19h dot net via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97976

Bug ID: 97976
   Summary: Optimization regression in 10.1 for lambda passed as
template argument
   Product: gcc
   Version: 10.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: peter at int19h dot net
  Target Milestone: ---

The following C++11 and above code:


extern const int* data;

template bool func(T callback)
{
for (const int* pi = data; pi; ++pi)
{
if (callback(*pi))
{
return false;
}
}
return true;
}

bool f0(int i)
{
return func([i](const int j){ return i == j; });
}



With GCC 10.1 with "-std=c++11 -O2" flags generates the following:

f0(int):
cmp QWORD PTR data[rip], 0
seteal
ret


While GCC 9.3 with the same command line flags generates the following:

f0(int):
mov rax, QWORD PTR data[rip]
testrax, rax
jne .L3
jmp .L4
.L7:
add rax, 4
.L3:
cmp edi, DWORD PTR [rax]
jne .L7
xor eax, eax
ret
.L4:
mov eax, 1
ret


It looks like this regression started with GCC 10 and starts at -02
optimization level for C++11 and above. I have tested this with clang and msvc,
and they generate code similar to what is generated by gcc 9.3.

This behavior can also be seen in the Compiler Explorer here:

https://godbolt.org/z/r4zMnc

Thank you!
--peter