This is an archive of the discontinued LLVM Phabricator instance.

[LICM] Make isGuaranteedToExecute more accurate.
ClosedPublic

Authored by eli.friedman on Jun 8 2016, 7:31 PM.

Details

Summary

Make isGuaranteedToExecute use the
isGuaranteedToTransferExecutionToSuccessor helper, and make that helper
a bit more accurate.

There's a potential performance impact here from assuming that arbitrary
calls might not return. This probably has little impact on loads and
stores to a pointer because most things alias analysis can reason about
are dereferenceable anyway. The other impacts, like less aggressive
hoisting of sdiv by a variable and less aggressive hoisting around
volatile memory operations, are unlikely to matter for real code.

This also impacts SCEV, which uses the same helper. It's a minor
improvement there because we can tell that, for example, memcpy always
returns normally. Strictly speaking, it's also introducing
a bug, but it's not any worse than everywhere else we assume readonly
functions terminate.

Fixes http://llvm.org/PR27857.

Diff Detail

Repository
rL LLVM

Event Timeline

eli.friedman retitled this revision from to [LICM] Make isGuaranteedToExecute more accurate..
eli.friedman updated this object.
eli.friedman added a subscriber: llvm-commits.
sanjoy requested changes to this revision.Jun 8 2016, 7:56 PM
sanjoy edited edge metadata.

I have some minor nits inline. However, I think before adding Yet Another Special Case(TM) for the "readonly implies termination" rule we should at least try to scope out how much work it will be to do this right and introduce a "halting" or "always_returns" attribute, and infer them for trivially halting functions.

lib/Analysis/ValueTracking.cpp
3448 ↗(On Diff #60131)

I don't think we model trapping memory operations in the IR at all (volatile or not).

3481 ↗(On Diff #60131)

I'm not sure onlyAccessesArgMemory is correct. What about:

void f(volatile int* ptr) {
  while (true) *ptr = 1;
}
lib/IR/Instruction.cpp
15 ↗(On Diff #60131)

Why do you need this?

lib/Transforms/Scalar/LICM.cpp
401 ↗(On Diff #60131)

As a later change, can I ask you to please change these loops to use all_of or any_of?

776 ↗(On Diff #60131)

Nit: http:// or just PR....

This revision now requires changes to proceed.Jun 8 2016, 7:56 PM

I don't think anything has changed for "halting" since the last time it was discussed, about a year ago. I mean, we probably get a lot of the benefit by just marking all the LLVM intrinsics and libcalls halting (which is straightfoward, but tedious to go through and find the exceptions). We can add some additional markings in clang for stuff marked pure. Beyond that, for a function definition, the rules are that it doesn't unwind, doesn't call any non-halting function, and doesn't have any infinite loops. Finding calls to non-halting functions is easy. Not sure how we solve whether whether a function has an infinite loop; I think that was still up in the air the last time it was discussed. I think there's still some sort of pass manager problem that prevents accessing SCEV from functionattrs? Also, some people would prefer to assume side-effect-free loops terminate in C/C++, and it isn't clear exactly what accommodations we have to make for that.

I'm not actually 100% sure about the "doesn't unwind" bit; it might make sense to compute a "doesn't call longjmp" bit separately.

lib/Analysis/ValueTracking.cpp
3481 ↗(On Diff #60131)

I don't think volatile stores are allowed in "argmemonly" methods. It would be like allowing volatile loads in a "readonly" method. If we say argmemonly functions are allowed to use volatile stores, from an optimization perspective the attribute is exactly equivalent to inaccessiblemem_or_argmemonly.

lib/IR/Instruction.cpp
15 ↗(On Diff #60131)

Oops, leftover from an older version.

sanjoy accepted this revision.Jun 11 2016, 12:07 AM
sanjoy edited edge metadata.
sanjoy added a subscriber: broune.

I had intended to add this myself in D19210 (so I don't have fundamental issues with the change) but decided against it when @broune pointed out that while(1); is well defined C11. But given that D19210 was also LGTM'ed (I was misremembering this earlier), I think this can go in.

I think there's still some sort of pass manager problem that prevents accessing SCEV from functionattrs?

It is even worse, I think, since not all infinite control flow will show up as llvm::Loop instances, so even if you could use SCEV, that won't be enough -- we'd have to conservative in the face of any cyclic control flow we couldn't fully understand.

lib/Analysis/ValueTracking.cpp
3481 ↗(On Diff #60131)

SGTM

This revision is now accepted and ready to land.Jun 11 2016, 12:07 AM
This revision was automatically updated to reflect the committed changes.