Calling an instruction a "source" is basically another way to say "we
can't dataflow through this".
What I'm trying to say is that this is not really a property of the
instruction type.
I agree we should be adding annotations sparingly - that is, we should not
annotate something we can infer. But that's a semantic property, so I don't
really see why that means we should prohibit annotating certain
instructions on the syntactic level.
I'm not opposed to this per se, but I see it as a slippery slope
argument. One of the foundational design principles of LLVM is that
analysis results are inferred from the IR, not part of the IR. This
decision is hugely important for stability and extensibility of the
framework.
Agreed.
If we ever got to the day where we were putting !range on an add
instruction as part of a transform pass, that would clearly be several
steps too far.
Yes.
Admittedly, the only example I have in mind right now is the one under
discussion above - if we have:
%p = select i1 %a, i8* %x, i8 *y
call void foo(i8* nonnull %p)
Then after inlining foo, we lose the non-null information for %p unless we
annotate it - and we can't propagate it through the select. The same would
happen for a phi,
Are there cases where we loose information by inlining this example?
Yes. Are they common? I don't know. In particular, if foo contains an
unconditional load from %p, we don't actually loose any information by
inlining. Similarly, we can frequently infer the non-null fact from
another source.
If foo contains an unconditional load from %p, then the original nonnull
attribute was also redundant. I'm assuming we're talking about cases where
the original attribute contained information not available elsewhere.
Just to be clear, I want to spell out a distinction between having
metadata available for frontend annotation and having the optimizer itself
introduce metadata. The former is a much easier request because it implies
a much smaller maintenance burden.
The optimizer can already do this, using assumes. By allowing !nonnull on
more instructions we wouldn't actually be letting the optimizer do
something it couldn't do before, we'd just make the representation more
uniform. But I understand the point of view that it also makes potentially
undesirable optimizer behavior simpler and thus more appealing.
If we screw something up (compile time say), then only the frontend that
cared bears the cost. If we start having the optimizer itself introduce
metadata (or assumes, etc..), then the justification has to sufficient for
*all* frontends and use cases. In practice, that's going to be a much
higher bar to clear.
Maybe. In any case, I don't feel strongly about this, I was just trying to
understand the rationale.