[cfe-dev] Can indirect class parameters be noalias?

Florian Hahn via cfe-dev cfe-dev at lists.llvm.org
Wed Aug 26 09:45:24 PDT 2020


Hi,

> On Aug 4, 2020, at 18:32, David Rector via cfe-dev <cfe-dev at lists.llvm.org> wrote:
> 
> 
> 
>> On Aug 3, 2020, at 11:28 PM, Hal Finkel via cfe-dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
>> 
>> 
>> 
>> On 8/3/20 8:45 PM, John McCall wrote:
>>> On 31 Jul 2020, at 19:50, Hal Finkel wrote:
>>> 
>>> On 7/31/20 5:59 PM, James Y Knight wrote:
>>> 
>>> This discussion reminds me of an example I ran into a couple weeks ago, where the execution of the program is dependent precisely upon whether the ABI calls for the object to be passed indirectly, or in a register
>>> 
>>> In the case where NVRO is triggered, the class member foo_ is fully-constructed on the first line of CreateFoo (despite appearing as if that's only constructing a local variable). In the case where the struct is small enough to fit in a register, NVRO does not apply, and in that case, foo_ isn't constructed until after CreateFoo returns.
>>> 
>>> Therefore, I believe it's implementation-defined whether the following program has undefined behavior.
>>> 
>>> https://godbolt.org/z/YT9zsz <https://godbolt.org/z/YT9zsz> <https://godbolt.org/z/YT9zsz <https://godbolt.org/z/YT9zsz>>
>>> 
>>> #include <assert.h>
>>> 
>>> struct Foo {
>>>     int x;
>>> *    // assert fails if you comment out these unused fields!
>>> *    int dummy[4];
>>> };
>>> 
>>> struct Bar {
>>>     Bar() : foo_(CreateFoo()) {}
>>> 
>>>     Foo CreateFoo() {
>>>         Foo f;
>>>         f.x = 55;
>>>         assert(foo_.x == 55);
>>>         return f;
>>>     }
>>>     Foo foo_;
>>> };
>>> 
>>> int main() {
>>>     Bar b;
>>> }
>>> 
>>> Looks that way to me too. The example in 11.10.5p2 sort of makes this point as well (by pointing out that you can directly initialize a global this way).
>>> 
>>> It does seem hard to argue that this is invalid under the specification. To me it seems like it clearly ought to be invalid, though. Note that Clang has always emitted return address arguments as noalias, so this has immediate significance.
>>> 
>>> If I were writing the specification, I would rewrite the restriction in [class.cdtor]p2 to say that pointers derived by naming a returned/constructed object do not formally point to the object until the function actually returns, even if the copy is elided. That would make James’s example undefined behavior.
>>> 
>>> John.
>>> 
>> 
>> I agree. It seems like we should be able to make a sanitizer detect this kind of mistake as well (although the general case will require some msan-like propagation scheme).
>> 
>>  -Hal
>> 
> 
> On second thought I agree as well — i.e. allow both the NRVO and the noalias optimizations to be applied as they currently are, and adjust the standard so that any code which would break due to those optimizations should be considered undefined.  
> 
> That would be consistent with the proposal of making escaping pointers within a constructor of a trivially-copyable class undefined behavior.
> 
> And more generally: if there are any other instances in which the compiler is currently forced to be pessimistic, just to handle a few weird usages which are technically allowed, I think by all means we should ask the standard to explicitly address those, via the same approach: the typical, more-optimizable cases should be allowed to fully optimize, by making the rare, less-optimizable cases undefined behavior.  
> 

It would be great to make some progress on the issue, but unfortunately I am unclear what the next steps should be?

As mentioned earlier, I added a patch to add noalias under a flag (https://reviews.llvm.org/D85473). Are there any concerns/objections on this as a first step?

Whether to enable it by default can then be discussed separately. IIUC from the discussion, we would need an adjustment to the standard along to lines of John’s proposal to making escaping pointers within a constructor of a trivially-copyable class undefined behavior. Are there any pointers/suggestions on how to best go about that?

> But in tandem, the standard should also introduce attributes that allow advanced users to explicitly opt out of those optimizations (e.g. "forcecopy" or "maybealias" or whatever) to allow their weird cases to remain standard compliant.  Nobody loses.
> 
> People write C and C++ because they want the fastest possible compiled code — the standard should get out of the way wherever it is obstructing optimization.
> 

Agreed, although this change seems to have the potential to break a very small subset of code out there in a very subtle manner, without an easy way to detect that. But maybe we can detect and warn about the most common/obvious violations at least and that is enough?

Cheers,
Florian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200826/73c69eae/attachment-0001.html>


More information about the cfe-dev mailing list