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

Piotr Padlewski via cfe-dev cfe-dev at lists.llvm.org
Wed Dec 5 14:57:51 PST 2018

śr., 5 gru 2018 o 18:10 Philip Reames <listmail at philipreames.com>

> On 12/5/18 12:57 AM, Piotr Padlewski wrote:
> śr., 5 gru 2018 o 00:22 John McCall via cfe-dev <cfe-dev at lists.llvm.org>
> napisał(a):
>> On 4 Dec 2018, at 17:50, Philip Reames wrote:
>> Skimming along, apologies if I'm repeating something which already got
>> said.
>> If I understand this correctly, the basic problem we're trying to solve
>> is to use a local hint (the invariant.group) to make a global assumption
>> about other code which might exist elsewhere outside the function.  The
>> attribute proposed can basically be phrased as describing a universe of
>> functions within which our desired global property holds.  There's an
>> ambiguity about what is allowed to be assumed about code outside that
>> universe.
>> I think it's important to note that we have a precedent of something
>> similar to this in TBAA.  TBAA information coming from different modules
>> has the same base problem.  We solve it by using the "root" of the TBAA
>> tree as a scope descriptor, and essentially making two TBAA nodes from
>> distinct roots incomparable.
>> Can someone explain concisely why a similar scheme couldn't be used to
>> solve this problem?
>> TBAA is conservative in *two* ways:
>> - It allows two accesses to alias if they have TBAA nodes with different
>> roots.
>> - It allows two accesses to alias if only one of them has a TBAA node.
>> The second is what doesn't generalize: there are optimizations where you
>> need to
>> rely on transition points being explicitly identified. Looking at a
>> function
>> with no identified transition points, you don't know whether it actually
>> doesn't
>> transition or whether it was compiled without the transitions being
>> explicitly
>> marked. There's no way to extend the TBAA idea to make that work.
> The other reason why similar scheme doesn't work for !invariant.group is
> that we rely on a calls to launder/strip being present for some constructs
> to preserve
> information about invartianess of an object (like in the example from RFC).
> I'm really not sure I buy this.  You're effectively saying that you have
> two points which need to share a common root: 1) the "transition point" and
> 2) the invariant.group marker.  If it were possible to mark the transition
> point with a metadata node - is it? - the exact same rules as used for TBAA
> work just fine.
> p.s. It would help me a lot if you'd spell out specific examples of
> transition points.  I checked the RFC and don't see them.
> As described in previous RFC: Devirtualization v2
whenever we compare pointers to dynamic objects, we need to use firstly
strip invariant.group information with @llvm.strip.invariant.group.
If we wouldn't do that, then comparison between pointers to same memory,
one pointer carring old dynamic information (with invariant.group) with
another carring new information could result in
transform that replaces uses of new pointer with old one, like in example

void bar() {
 A *a = new A;
 A * b = new (a) B;
 if (a == b)

Now imagine that this invalid comparison is done in a module that do not
follow our rules, then if !invariant.group information would still be
preserved after inlining such module, it would
result in transform that we would not like to happen.  This is shown in the
example from current RFC

define void @with_devirtualization(i8* %p) supported_optimizations =
"clang.cxx.devirtualization" {
 %v1 = load i8, i8* %p, !invariant.group !0
 %p2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
 call void @without_devirtualization(i8* %p, i8* %p2)
 %v2 = load i8, i8* %p2, !invariant.group !0
 ret void

define void @without_devirtualization(i8* %p, i8* %p2) {
  %b = icmp eq i8* %p, %p2
  call void @llvm.assume(i1 %b)
  ret void

!0 = !{!"clang.cxx.devirtualization"}
declare void @llvm.assume(i1)
declare i8* @llvm.launder.invariant.group.p0i8(i8*)

I hope my short explanation is good enough, you can find longer explanation
in the previous RFC that I linked.

> On 12/4/18 11:24 AM, John McCall via llvm-dev wrote:
>> Note that IPO is generally permitted to partially inline or outline code,
>> and so good-faith optimizations that e.g. require two instructions to be
>> moved
>> in tandem or not at all must use tokens to establish that unbreakable
>> relationship.
>> I think the way your framing this is dangerous.  We absolutely can not
>> allow any annotation of this form to *weaken* the semantics of the existing
>> IR.  We can and should impose a criteria that any extension of this variety
>> strictly add information to the IR which might not have been previously
>> inferred.  We can then design rules for how to preserve our new information
>> as long as possible, but framing this in terms of disallowed
>> transformations is really a non-starter.
>> That's exactly what I was trying to convey here. Authors of good-faith
>> optimizations need to design their representations so that transformations
>> that know nothing about their optimizations but merely preserve semantics
>> and well-formed IR structure will not break their representations. The
>> only
>> transforms that need to know about the existence of good-faith
>> optimizations
>> are interprocedural optimizations; furthermore, those optimizations don't
>> need to know about any good-faith optimizations specifically, they just
>> need
>> to understand how to correctly update the supported_optimizations list.
>> That is a very small burden on IPO that enables an interesting class of
>> language-specific optimizations.
>> John.
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20181205/7f4f11ac/attachment.html>

More information about the cfe-dev mailing list