[Bug tree-optimization/87314] pointless comparison of malloc result to a string not eliminated
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
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
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
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
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
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
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
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
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
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 (); }