[cfe-dev] [llvm-dev] RFC: Supported Optimizations attribute

John McCall via cfe-dev cfe-dev at lists.llvm.org
Tue Dec 4 12:50:00 PST 2018


On 4 Dec 2018, at 14:59, Sanjoy Das wrote:
> On Tue, Dec 4, 2018 at 11:24 AM John McCall <jmccall at apple.com> wrote:
>>> In other words, certain things are UB in functions tagged with
>>> supported_optimizations that are not UB otherwise? This breaks code
>>> hoisting transformations right? I.e.
>>> isSafeToSpeculativelyExecute(Inst) will have to return false if Inst
>>> is in a function with a non-empty supported_optimizations?
>>>
>> Good question. I would consider that to be an unacceptable intrusion:
>> intraprocedural transforms should never have to be aware of
>> supported_optimizations (unless they're implementing a good-faith
>> optimization, of course) and interprocedural transforms should only 
>> have
>> to be aware of supported_optimizations in the narrow sense outlined
>> by Piotr. If something about the optimization's representation in IR
>> is unsafe to speculate, it should be made impossible to speculate for
>> standard semantic/structural reasons, like having apparently 
>> arbitrary
>> side-effects.
>>
>> I think the right way to formalize this is to say that, while the
>> good-faith optimization may impose additional UB rules on the 
>> function,
>> it must guarantee that transforms that are well-behaved as described
>> above --- i.e. that preserve standard structure and semantics and 
>> which,
>> if interprocedural, appropriately honor supported_optimizations --- 
>> will
>> never introduce new UB.
>
> I see.  Would it be correct to say that a good faith optimization `O`
> assumes that a certain construct(s), `FOO`, does not occur in the
> *trace* of the program within the function tagged with
> supported_optimizations={O}?

I'm not sure that's a useful way of thinking about it.  Usually the 
assumption
will be something more like "Thing 1 does not occur after Event A but 
before any
occurrence of Event B", and we can clearly mark Events A and B in the 
IR, but
there might be dozens of different code patterns which all qualify as 
Thing 1.
This would have to be a good-faith optimization because a 
non-cooperative
function might not mark Events A and B in the IR, so inlining that into 
a
cooperative function could lead to miscompilation.

> Also `FOO` has to be side effecting so
> LLVM cannot speculate it into existence (e.g. `FOO` can't be
> "getelementptr with a certain property").

I don't think "side effecting" is *always* the right rule, but yes:

- If something about the sequence shouldn't be speculated, the 
optimization
   should arrange it so that transforms following standard rules can't
   speculate it.  For example, if you have a language rule that 
guarantees
   that a certain global variable is guaranteed to be constant past a 
certain
   point in the program, you can mark that point with an intrinsic, but 
that
   intrinsic needs to be made non-speculable, and the easiest way to 
achieve
   that is to ensure that it claims to have arbitrary side-effects so 
that code
   which doesn't specifically know about this intrinsic won't speculate 
it.

- In general, all the intrinsic calls, metadata, and so on that 
participate
   in the optimization should be marked in some way that's specific to 
the
   optimization.  Formally, this requires that arbitrary transforms that 
aren't
   aware of the optimization can't just *sua sponte* add 
optimization-tagged
   constructs to a function, as opposed to e.g. cloning or moving them 
from
   somewhere else, but that seems like a pretty safe assumption. :)

John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20181204/30ab2645/attachment.html>


More information about the cfe-dev mailing list