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

--- Comment #1 from Thiago Macieira <thiago at kde dot org> ---
The following is the analysis done by the AI. I cannot verify the GIMPLE
analysis, but the outer reasoning is sound:

1. While inlining `indexOf` into `f`, the inliner's function summary evaluates
   `__builtin_constant_p(s.m_size)` as true, because `m_size == 1` is known at
   the call site. The edge to `findString()` gets `predicate: (false)` and is
   redirected to `__builtin_unreachable()`. The `095i.inline` dump shows:
   ```
   Introduced new external node (void __builtin_unreachable()/9).
   void __builtin_unreachable()/9 unreachable ... predicate: (false)
   ```
   After IPA (`fixup_cfg3`) the body looks like this:
   ```
   s = sought;
   s$m_size_12 = s.m_size;
   _13 = __builtin_constant_p (s$m_size_12);
   if (_13 != 0) goto <bb 5>; else goto <bb 7>;
   <bb 5>: if (s$m_size_12 == 1) goto <bb 6>; else goto <bb 7>;
   <bb 6>: _14 = findChar (_10); ...
   <bb 7>: __builtin_unreachable ();
   ```
2. The later passes (FRE/VRP) never forward the value `1` into the
   loop-carried load `s.m_size`, so `vrp1` folds `__builtin_constant_p
(s$m_size_12)`
   to 0. The only remaining path then leads to `__builtin_unreachable()`, and
the
   function body is deleted.

So the IPA-time evaluation of `__builtin_constant_p` and its later folding
disagree. Either the inliner shouldn't turn the non-constant arm into
`unreachable` unless it can guarantee the builtin will fold to 1, or the
folding of a `__builtin_constant_p` whose predicate was already assumed true
must be consistent with that.

Adding `[[assume((unsigned long)m_size <= 0x3ffffffffffffffe)]]` in a `size()`
accessor that `scan` calls makes the miscompile show up at `-O3` too.
GCC emits `.ASSUME (fn, &sought)` and that blocks the same forwarding.

Reply via email to