[PATCH] D70749: [InstCombine] do not insert nonnull assumption for undef

Bob Haarman via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 27 14:00:40 PST 2019


inglorion added a comment.

> How was DAE able to replace an argument with undef which was fed to strlen? Is that the real bug?

The bug I'm working on is not in the strlen example the original optimization was written for. It is in this fragment, simplified from libc++'s locale __widen_and_group_float:

  template <>
  void
  __num_put<char>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
                                           char* __ob, char*& __op, char*& __oe,
                                           const locale& __loc)
  {
      const ctype<char>& __ct = use_facet<ctype<char>>(__loc);
      if (__nb < __ne)                                                                                                                        
      {
          if (*__nb == '.')
          {
              *__ob++ = '.';
          }
          else
          {
              *__ob++ = __ct.widen(*__nb);
          }
      }
      __op = __ob;
  }

In the IR, the call to widen is in a basic block before the assignment to *__ob (I suppose because the declaration isn't nounwind). Its first parameter, __ct, is nonnull. When compiling with -fwhole-program-vtables, we are able to determine widen's properties more precisely. We discover that it does not in fact use __ct, so deadargelim replaces that with undef. We discover that we can sink it to the BB that the assignment to *__ob is in, so instcombine does that, and emits @llvm.assume(i1 undef) in place of the original call site. Then simplifycfg notices that this branch of the if statement invokes undefined behavior, and so the other branch must be taken, and the code simplifies to something like

  template <>
  void
  __num_put<char>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
                                           char* __ob, char*& __op, char*& __oe,
                                           const locale& __loc)
  {
    if (__nb < __ne)
    {
      *__ob++ = '.';
    }
    __op = __ob;
  }

The important difference from the strlen example is that widen in this case really does not use the nonnull parameter in question.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70749/new/

https://reviews.llvm.org/D70749





More information about the llvm-commits mailing list