Message ID | 20171219172355.GU2353@tucnak |
---|---|
State | New |
Headers | show |
Series | Small load strlen opt follow-up improvement (PR tree-optimization/83444) | expand |
On December 19, 2017 6:23:55 PM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote: >Hi! > >As the testcase shows, we weren't handling the case where we have >_34 = MEM_REF[&b, 4B]; >- we would (if it exists) find the string length for b.a, but not >for the second field. Using get_addr_stridx handles that well. >The reason to use get_stridx on the MEM_REF first operand is to handle >the case when the MEM_REF is based on SSA_NAME, that is something >get_addr_stridx doesn't handle. > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? OK. Richard. >2017-12-19 Jakub Jelinek <jakub@redhat.com> > > PR tree-optimization/83444 > * tree-ssa-strlen.c (strlen_check_and_optimize_stmt): For the > character load case, if get_stridx on MEM_REF's operand doesn't > look usable, retry with get_addr_stridx. > > * gcc.dg/strlenopt-38.c: New test. > >--- gcc/tree-ssa-strlen.c.jj 2017-12-19 08:43:35.000000000 +0100 >+++ gcc/tree-ssa-strlen.c 2017-12-19 12:52:37.007267178 +0100 >@@ -3155,14 +3155,27 @@ strlen_check_and_optimize_stmt (gimple_s > { > tree off = integer_zero_node; > unsigned HOST_WIDE_INT coff = 0; >- int idx = -1; >+ int idx = 0; > tree rhs1 = gimple_assign_rhs1 (stmt); > if (code == MEM_REF) > { > idx = get_stridx (TREE_OPERAND (rhs1, 0)); >- off = TREE_OPERAND (rhs1, 1); >+ if (idx > 0) >+ { >+ strinfo *si = get_strinfo (idx); >+ if (si >+ && si->nonzero_chars >+ && TREE_CODE (si->nonzero_chars) == INTEGER_CST >+ && (wi::to_widest (si->nonzero_chars) >+ >= wi::to_widest (off))) >+ off = TREE_OPERAND (rhs1, 1); >+ else >+ /* This case is not useful. See if get_addr_stridx >+ returns something usable. */ >+ idx = 0; >+ } > } >- else >+ if (idx <= 0) > idx = get_addr_stridx (rhs1, NULL_TREE, &coff); > if (idx > 0) > { >--- gcc/testsuite/gcc.dg/strlenopt-38.c.jj 2017-12-19 >08:43:35.000000000 +0100 >+++ gcc/testsuite/gcc.dg/strlenopt-38.c 2017-12-19 12:53:19.006730543 >+0100 >@@ -36,3 +36,14 @@ baz (void) > if (s.b[0] != 0) > abort (); > } >+ >+void >+boo (void) >+{ >+ struct S s; >+ strcpy (s.b, "012"); >+ strcpy (s.c, ""); >+ strcpy (s.b, s.c); >+ if (strlen (s.b) != 0) >+ abort (); >+} > > Jakub
On 12/19/2017 10:23 AM, Jakub Jelinek wrote: > Hi! > > As the testcase shows, we weren't handling the case where we have > _34 = MEM_REF[&b, 4B]; > - we would (if it exists) find the string length for b.a, but not > for the second field. Using get_addr_stridx handles that well. > The reason to use get_stridx on the MEM_REF first operand is to handle > the case when the MEM_REF is based on SSA_NAME, that is something > get_addr_stridx doesn't handle. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2017-12-19 Jakub Jelinek <jakub@redhat.com> > > PR tree-optimization/83444 > * tree-ssa-strlen.c (strlen_check_and_optimize_stmt): For the > character load case, if get_stridx on MEM_REF's operand doesn't > look usable, retry with get_addr_stridx. > > * gcc.dg/strlenopt-38.c: New test. OK. jeff
--- gcc/tree-ssa-strlen.c.jj 2017-12-19 08:43:35.000000000 +0100 +++ gcc/tree-ssa-strlen.c 2017-12-19 12:52:37.007267178 +0100 @@ -3155,14 +3155,27 @@ strlen_check_and_optimize_stmt (gimple_s { tree off = integer_zero_node; unsigned HOST_WIDE_INT coff = 0; - int idx = -1; + int idx = 0; tree rhs1 = gimple_assign_rhs1 (stmt); if (code == MEM_REF) { idx = get_stridx (TREE_OPERAND (rhs1, 0)); - off = TREE_OPERAND (rhs1, 1); + if (idx > 0) + { + strinfo *si = get_strinfo (idx); + if (si + && si->nonzero_chars + && TREE_CODE (si->nonzero_chars) == INTEGER_CST + && (wi::to_widest (si->nonzero_chars) + >= wi::to_widest (off))) + off = TREE_OPERAND (rhs1, 1); + else + /* This case is not useful. See if get_addr_stridx + returns something usable. */ + idx = 0; + } } - else + if (idx <= 0) idx = get_addr_stridx (rhs1, NULL_TREE, &coff); if (idx > 0) { --- gcc/testsuite/gcc.dg/strlenopt-38.c.jj 2017-12-19 08:43:35.000000000 +0100 +++ gcc/testsuite/gcc.dg/strlenopt-38.c 2017-12-19 12:53:19.006730543 +0100 @@ -36,3 +36,14 @@ baz (void) if (s.b[0] != 0) abort (); } + +void +boo (void) +{ + struct S s; + strcpy (s.b, "012"); + strcpy (s.c, ""); + strcpy (s.b, s.c); + if (strlen (s.b) != 0) + abort (); +}