https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96351

            Bug ID: 96351
           Summary: missed opportunity to optimize out redundant loop
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: felix.yang at huawei dot com
  Target Milestone: ---

inline unsigned int
stringLen(const short* const src)
{
    if (src == 0 || *src == 0) {
        return 0;
    } else {
        const short* pszTmp = src + 1;

        while (*pszTmp)
            ++pszTmp;

        return (unsigned int)(pszTmp - src);
    }
}

extern void bar();

void foo(const short* const str) {
    unsigned int len = stringLen(str);
    if (!len) {
        bar();
    }
}

When stringLen is inlined into foo, the else block in stringLen can be
simplified into non-zero, thus eliminating the while loop. This looks like a
tree VRP issue, but this pass does not work as expected for this test case.

$ g++ -S -O2 foo.cpp -fdump-tree-vrp

Consider function foo, value ranges after VRP does not help here:
 48
 49 .MEM_1: <<< error >>> VARYING
 50 str_3(D): const short int * const VARYING
 51 _6: short int VARYING
 52 str_7: const short int * const [1B, +INF]  EQUIVALENCES: { str_3(D) } (1
elements)
 53 pszTmp_8: const short int * [1B, +INF]  EQUIVALENCES: { pszTmp_10 } (1
elements)
 54 pszTmp_9: const short int * const [1B, +INF]
 55 pszTmp_10: const short int * const [1B, +INF]
 56 _11: short int VARYING
 57 pszTmp_12: const short int * [1B, +INF]
 58 _13: unsigned int [0, 0]
 59 _14: long int VARYING
 60 _15: long int [-4611686018427387904, 4611686018427387903]
 61 _16: unsigned int VARYING
 62 _18: unsigned int [0, 0]
 63 pszTmp_19: const short int * [1B, +INF]  EQUIVALENCES: { pszTmp_10 } (1
elements)

 ......

 93   <bb 4> [local count: 439750964]:
 94   pszTmp_9 = str_3(D) + 2;
 95
 96   <bb 5> [local count: 3997736055]:
 97   # pszTmp_10 = PHI <pszTmp_9(4), pszTmp_12(6)>
 98   _11 = *pszTmp_10;
 99   if (_11 == 0)
100     goto <bb 7>; [11.00%]
101   else
102     goto <bb 6>; [89.00%]
103
104   <bb 6> [local count: 3557985095]:
105   pszTmp_12 = pszTmp_10 + 2;
106   goto <bb 5>; [100.00%]
107
108   <bb 7> [local count: 439750964]:
109   # pszTmp_8 = PHI <pszTmp_10(5)>
110   _14 = pszTmp_8 - str_3(D);
111   _15 = _14 /[ex] 2;
112   _16 = (unsigned int) _15;
113   if (_16 == 0)
114     goto <bb 8>; [3.91%]
115   else
116     goto <bb 9>; [96.09%]
117
118   <bb 8> [local count: 354334798]:
119   bar ();
120
121   <bb 9> [local count: 1073741824]:
122   return;

Any suggestions to proceed?

Reply via email to