[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2019-05-03 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

--- Comment #10 from Richard Biener  ---
(In reply to Jakub Jelinek from comment #9)
> The question is how far we want to go and what we just ignore.
> With -fmerge-all-constants, we can have:
> const char var[] = "foobar";
> int foo (void) { return &var[0] != "foobar"; }
> which will likely be now miscompiled.

GCC 8 produces the following and so doesn't actually merge the constants

.LC0:
.string "foobar"
.section.text.startup,"ax",@progbits
.p2align 4,,15
.globl  main
.type   main, @function
main:
.LFB0:
.cfi_startproc
movl$var, %eax
cmpq$.LC0, %rax
setne   %al
movzbl  %al, %eax
ret
.cfi_endproc
.LFE0:
.size   main, .-main
.globl  var
.section.rodata.str1.1
.type   var, @object
.size   var, 7
var:
.string "foobar"

And with -O0 it's even more obvious:

var:
.string "foobar"
.LC0:
.string "foobar"

and yes, we now optimize this.

> But we could even have two sources,
> const char var2[] = "foobar";
> compiled with -fmerge-all-constants and
> extern char var2[];
> int bar (void) { return &var2[0] != "foobar"; }
> compiled with -fmerge-constants (the default).
>
> So, can we e.g. optimize less if we see flag_merge_all_constants and a
> TREE_READONLY decl(s) (both the above first case and your const int case)?
> If the decl(s) have DECL_INITIAL and bind to current TU, we could of course
> check further the initializers, and ignore the nasty second case above, by
> saying that
> if you define vars as const and declare as non-const, it is your problem and
> similarly, if you -fmerge-all-constants the defining TUs but not uses of
> those decls, it is again your fault?  I'd lean towards that.

I didn't manage to merge the variable and the string literal, so I believe
this is a theoretical issue?

[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2019-05-03 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

--- Comment #9 from Jakub Jelinek  ---
The question is how far we want to go and what we just ignore.
With -fmerge-all-constants, we can have:
const char var[] = "foobar";
int foo (void) { return &var[0] != "foobar"; }
which will likely be now miscompiled.  But we could even have two sources,
const char var2[] = "foobar";
compiled with -fmerge-all-constants and
extern char var2[];
int bar (void) { return &var2[0] != "foobar"; }
compiled with -fmerge-constants (the default).

So, can we e.g. optimize less if we see flag_merge_all_constants and a
TREE_READONLY decl(s) (both the above first case and your const int case)?
If the decl(s) have DECL_INITIAL and bind to current TU, we could of course
check further the initializers, and ignore the nasty second case above, by
saying that
if you define vars as const and declare as non-const, it is your problem and
similarly, if you -fmerge-all-constants the defining TUs but not uses of those
decls, it is again your fault?  I'd lean towards that.

[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2019-05-03 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

--- Comment #8 from Richard Biener  ---
(In reply to Jakub Jelinek from comment #7)
> Is it safe with -fmerge-all-constants if the decls are TREE_READONLY?

I don't think DECL vs STRING_CST is any special here (or well, STRING_CSTs
will end up in mergeable string sections).  It's probably more a question
for

const int a = 2;
const int b = 2;

int main() { return &a != &b; }

which we "miscompile" since forever with -fmerge-all-constants.

[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2019-05-03 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jakub at gcc dot gnu.org

--- Comment #7 from Jakub Jelinek  ---
Is it safe with -fmerge-all-constants if the decls are TREE_READONLY?

[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2019-05-03 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

Richard Biener  changed:

   What|Removed |Added

 Status|ASSIGNED|RESOLVED
 Resolution|--- |FIXED

--- Comment #6 from Richard Biener  ---
Fixed.

[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2019-05-03 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

--- Comment #5 from Richard Biener  ---
Author: rguenth
Date: Fri May  3 10:44:17 2019
New Revision: 270845

URL: https://gcc.gnu.org/viewcvs?rev=270845&root=gcc&view=rev
Log:
2019-05-03  Richard Biener  

PR middle-end/87314
* match.pd (cmp (convert1?@2 addr@0) (convert2? addr@1)):
Handle STRING_CST vs DECL or STRING_CST.

* gcc.dg/pr87314-1.c: New testcase.

Added:
trunk/gcc/testsuite/gcc.dg/pr87314-1.c
Modified:
trunk/gcc/ChangeLog
trunk/gcc/match.pd
trunk/gcc/testsuite/ChangeLog

[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2019-01-10 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

Richard Biener  changed:

   What|Removed |Added

 Status|NEW |ASSIGNED
   Assignee|unassigned at gcc dot gnu.org  |rguenth at gcc dot 
gnu.org

--- Comment #4 from Richard Biener  ---
Created attachment 45399
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45399&action=edit
patch for the string cases

OK, these special cases could be handled easily.  They should already
be covered by

/* When the addresses are not directly of decls compare base and offset.
   This implements some remaining parts of fold_comparison address
   comparisons but still no complete part of it.  Still it is good
   enough to make fold_stmt not regress when not dispatching to fold_binary. 
*/
(for cmp (simple_comparison)
 (simplify
  (cmp (convert1?@2 addr@0) (convert2? addr@1))
  (with

but we fall into

  (if (equal == 0
   && DECL_P (base0) && DECL_P (base1)
   /* If we compare this as integers require equal offset.  */
   && (!INTEGRAL_TYPE_P (TREE_TYPE (@2))
   || known_eq (off0, off1)))
   (switch
(if (cmp == EQ_EXPR)
 { constant_boolean_node (false, type); })
(if (cmp == NE_EXPR)
 { constant_boolean_node (true, type); })

which only handles decl vs. decl.

I'm not sure how to handle "foo" ==/!= "foo" though, dependent on string
merging they could be either equal or not equal.  I guess similar
for "foobar"+3 and "bar"?

So sth like the attached which is conservative about string-merging (delaying
to runtime).

[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2019-01-09 Thread glisse at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

--- Comment #3 from Marc Glisse  ---
It isn't just with malloc, the following are not optimized either.

int f(){ int a; return &a=="hello"; }
int g(){ return "bye"=="hello"; }

[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2018-09-17 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

Richard Biener  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
   Last reconfirmed||2018-09-17
 CC||rguenth at gcc dot gnu.org
 Ever confirmed|0   |1

--- Comment #2 from Richard Biener  ---
The issue is in ptrs_compare_unequal () which is limited because points-to
analysis doesn't conservatively propagate NULL and also because it doesn't
handle STRING_CST (similar reason, we drop all pointed-to-readonly-string).

[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated

2018-09-14 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314

--- Comment #1 from Martin Sebor  ---
Same here (Clang doesn't eliminate the test here though):

void f (void)
{
  void *p = __builtin_malloc (sizeof (void*));

  if (p == f)   // not folded
__builtin_abort ();
}

Here, GCC eliminates the equality test with a but not the one with b (Clang
eliminates neither):

char a[8] = "";
char b[8];

void f (void)
{
  void *p = __builtin_malloc (sizeof (void*));

  if (p == a)   // folded to false
__builtin_abort ();
}

void g (void)
{
  void *p = __builtin_malloc (sizeof (void*));

  if (p == b)   // not folded
__builtin_abort ();
}