This is an archive of the discontinued LLVM Phabricator instance.

[CodeGen] make nan builtins pure rather than const (PR37778)
ClosedPublic

Authored by spatel on Jun 13 2018, 9:53 AM.

Details

Summary

https://bugs.llvm.org/show_bug.cgi?id=37778
...shows a miscompile resulting from marking nan builtins as 'const'.

The nan libcalls/builtins take a pointer argument:
http://www.cplusplus.com/reference/cmath/nan-function/
...and the chars dereferenced by that arg are used to fill in the NaN constant payload bits.

"const" means that the pointer argument isn't dereferenced. That's translated to "readnone" in LLVM.
"pure" means that the pointer argument may be dereferenced. That's translated to "readonly" in LLVM.

This change prevents the IR optimizer from killing the lead-up to the nan call here:

double a() {
  char buf[4];
  buf[0] = buf[1] = buf[2] = '9';
  buf[3] = '\0';
  return __builtin_nan(buf);
}

...the optimizer isn't currently able to simplify this to a constant as we might hope, but this patch should solve the miscompile.

Diff Detail

Repository
rL LLVM

Event Timeline

spatel created this revision.Jun 13 2018, 9:53 AM
lebedev.ri accepted this revision.Jun 13 2018, 10:19 AM

Makes sense.

This revision is now accepted and ready to land.Jun 13 2018, 10:19 AM
This revision was automatically updated to reflect the committed changes.
rsmith added a subscriber: rsmith.Jun 13 2018, 1:39 PM

Can we mark these as argmemonly?

Can we mark these as argmemonly?

Header comment in include/clang/Basic/Builtins.def does not list that as a possibility.

Can we mark these as argmemonly?

I wasn't aware of that one, but it sounds accurate for nan() and friends:

argmemonly
  This attribute indicates that the only memory accesses inside function are loads and stores from objects pointed to by its pointer-typed arguments, with arbitrary offsets. Or in other words, all memory operations in the function can refer to memory only using pointers based on its function arguments. Note that argmemonly can be used together with readonly attribute in order to specify that function reads only from its arguments.

But as Roman noted, we're going to have to update the list of possibilities to include "NoAliasAttr"? And might need to adjust the logic where that gets mapped to the LLVM attr.