[llvm-commits] [PATCH] Invariants (and Assume Aligned) - LLVM

Andrew Trick atrick at apple.com
Mon Dec 10 11:02:44 PST 2012


On Dec 9, 2012, at 10:00 PM, Hal Finkel <hfinkel at anl.gov> wrote:
> Fair enough, but it is not clear to me that we have the correct side-effect model for this to work. If I have:
> 
> void foo(int a, int b) {
>  if (a > 0) {
>    __builtin_assume(b == 3);
>    bar(a, b);
>  }
> 
>  bar2(a, b);
> }
> 
> given that the intrinsic is free (in terms of execution cost) and has no side effects in the usual sense, what prevents some transformation from moving the assumption outside of the if statement? I suppose that we could mark the assumption intrinsic as having unmodeled side effects, but that would be unproductive.

It would be generally useful to model an intrinsic that is free and not a strong use but does have control dependence. That's what I call a meta-intrinsic. We currently get by with marking them memory writers, which is too conservative, or introducing special cases, as done for debug info.

>> Well said. I appreciate that this is a problem worth solving, but I
>> think
>> adding ephemeral values to the IR will cause a perpetual headache. We
>> need to consider other solutions.
> 
> Introducing invariants would enable much more than just this use case. As you probably know, invariants have been an often-requested feature for quite some time, and Chandler suggested approaching the alignment problem using invariants as a way to simultaneously advance both desires.

Absolutely. I'd like to know what the tradeoff is between ephemeral values and a metadata language.

> Doing this seems to have two options:
> 1. Describe invariants using LLVM IR (which naturally seems to give the ephemeral values problem)
> 2. Create a new language for describing invariants
> Expressing invariants in the IR means that they naturally get transformed and updated along with the values they describe.
> 
> As a quick summary, here are some uses that have been mentioned for invariants:
> - Implementing pointer-alignment assumptions
> - Providing additional constraints to SE (and Polly)
> - Transplanting loop-bound information, etc. into outlined functions representing loop bodies (for OpenMP, etc.)
> (from Chandler on IRC)
> - Declaring that two values are equivalent to avoid redundant loads
> - Declaring that one vptr being loaded is equivalent to some constant or some other vptr we may have knowledge about (similar to the previous use, but the goal is indirect call resolution, not load removal)
> - Declaring that some predicate is known, such as a pointer being non-null, to delete branches on that predicate

It doesn't seem like the metadata language to describe these would be terribly complicated. I could be wrong.

Making an example of your first test case:

define i32 @foo(i32* nocapture %a) nounwind uwtable readonly {
entry:

-  %ptrint = ptrtoint i32* %a to i64
-  %maskedptr = and i64 %ptrint, 31
-  %maskcond = icmp eq i64 %maskedptr, 0
-  tail call void @llvm.invariant(i1 %maskcond)

+  tail call void @llvm.invariant(metadata !{i32* %a}, metadata !0) ; align(%a, 8, 0)

 %0 = load i32* %a, align 4, !tbaa !0
 ret i32 %0

+ !0 = metadata !{i8 1, i16 8, i16 0} ; TAG #1 = alignment

I don't like reading metadata better than anyone else, but that's a superficial concern. I like this approach from the optimizer's perspective.

There may also be a concern of the overhead. e.g. too many TrackingVHs or the size of metadata. But these are engineering problems that don't have broader design implications.

>> I would like the underlying object to have metadata that captures its
>> alignment, and possibly offset relative to an aligned address. I
>> don't
>> see why this couldn't be done with an intrinsic that takes a metadata
>> argument refering to the underlying object's value.
> 
> Could you type out an explicit example of what you're proposing? To handle just the alignment case, I'm not sure that we need metadata at all.

You don't need metadata. You could have an llvm.align(i8*, #, #). But you still need to solve the problem of introducing new uses. I only see two options:

1) Make use iterators smart enough to know about meta-intrinsics. Callers of hasOneUse, use_empty need to know whether they care about meta-uses. Scary.

2) Meta-data users that add handles. Expensive?

-Andy





More information about the llvm-commits mailing list