[llvm-dev] RFC: Supported Optimizations attribute
John McCall via llvm-dev
llvm-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/llvm-dev/attachments/20181204/30ab2645/attachment.html>
More information about the llvm-dev
mailing list