[LLVMdev] [RFC] New function attributes for errno-setting functions
Chris Lattner
clattner at apple.com
Tue Sep 17 21:37:53 PDT 2013
On Sep 17, 2013, at 1:45 PM, Hal Finkel <hfinkel at anl.gov> wrote:
>> Also, the "errno-ignored" or equivalent attribute brings up this
>> question:
>> given this code
>> x = cos(y); // assume "errno-ignored"
>> z = global;
>> is it safe to infer that "global" is not errno?
>
> Unfortunately, I fear that the answer is no; at least, not without some further target-specific information. In general, any global could be errno. On the other hand, if we know that we're on Darwin, or using glibc, or whatever, then we could likely say something more.
It has been over 5 years since I've thought about this serious, but here are some of my thoughts from then.
There are lots of good reasons to want to model errno aggressively. If you're going to do it, a function attribute "does not touch errno" is a good thing to have. The frontend then puts this on well-known libc functions.
It makes sense to model this as an attribute (as opposed to hard coding the well-known list in the optimizer) for at least three reasons:
1. The mid-level optimizer can propagate it through the callgraph.
2. Things like -fno-math-errno to set it in a front-end sensitive way.
3. Some call sites can have it, even if the function in general cannot. For example when it is statically provable that the argument to a sqrt is positive.
The major design problem you need to solve (which you identified) is that you need to know how to recognize explicit accesses to errno. You can't break code like:
sqrt(-1);
printf("%d", errno);
... even though errno is a macro that expands out to target-specific code for thread local errno processing.
There are better and worse ways to handle this. The ideal mode is where we can change the system header files. In that case you can change the definition of errno. For example, the mac has sys/errno.h that has:
#define errno (*__error())
we could, in principle, change this to:
#define errno (*__builtin_errno_address())
Clang would then lower this to an llvm IR "@llvm.errno.address" intrinsic, then have the code generator lower that to the right target-specific thing (a call to __error() in this case).
I don't know how feasible this is to roll out on linux or other platforms which may or may not have sympathetic libc maintainers. Assuming they aren't sympathetic, you only have one less-great option IMO. That is that you hack Clang to pattern match a well-known AST pattern into the __builtin_errno_address builtin. For targets without a well-known pattern, it would never add the "does not touch errno" attribute.
I don't think it is defensible to try to pattern match this in the IR optimizer. It would be too fragile, and putting that level of target-specific C idiom stuff into the optimizer makes me queasy.
-Chris
More information about the llvm-dev
mailing list