Missed range propagation/loop unswitch/GVN opportunity?

Hi,
Apologize for the vague title, as I am not quite sure which
optimization is supposed to be able to handle this case.
Consider the following code:

#include <cstring>

class const_iterator {
  const char *charPtr_{nullptr};
  const char16_t *char16Ptr_{nullptr};
public:
  const_iterator();
  const_iterator &operator++() {
  if (charPtr_) ++charPtr_; else ++char16Ptr_;
  return *this;
}
char16_t operator*() const {
  return charPtr_ ? *charPtr_ : *char16Ptr_;
}
};

bool check(char16_t c, int &v);

int foo(const_iterator itr) {
  int tmp = 0;
  while (check(*itr, tmp))
    ++itr;
  return tmp;
}

You can see the generated code by both Clang and GCC:
https://godbolt.org/z/xdT78K.
Within the while loop, GCC is able to identify that the underline
charPtr_ of itr is either always null or never null, hence the check
of charPtr_ is moved out of the loop and never checked within the loop
(it is done during vrp1 step). However with Clang, although it is able
to duplicate part of the loop body, it is still checking the nullness
of charPtr_ within the loop (the first test instruction in .LBB0_1).
Why isn't Clang able to move that predicate out of the loop?