Stream: project-inline-asm

Topic: Should pure imply nomem


Amanieu (Mar 01 2020 at 17:10, on Zulip):

I noticed that LLVM will only optimize away an asm with unused outputs if both the pure and nomem flags are set.

Amanieu (Mar 01 2020 at 17:11, on Zulip):

Based on our current rules for pure, code using it can't read or write memory anyways.

Amanieu (Mar 01 2020 at 17:12, on Zulip):

I can see 2 options:
a) pure implies nomem and it is an error to specify both.
b) pure requires the nomem flag to also be set. It is an error otherwise.

Amanieu (Mar 01 2020 at 17:18, on Zulip):

Oh wait actually it's even worse. LLVM will happily remove a nomem or readonly asm, even if it is marked as sideeffect.

Amanieu (Mar 01 2020 at 17:43, on Zulip):

OK, let's consider the cases we need to model:

nagisa (Mar 01 2020 at 17:44, on Zulip):

I would argue that sideeffect and nomem being specified at the same time is a bug, as those are mutually exclusive in LLVM AFAIK.

Amanieu (Mar 01 2020 at 17:44, on Zulip):

And here are the LLVM attributes we have to work with: readnone, readonly, writeonly, argmemonly, inaccessiblememonly, inaccessiblemem_or_argmemonly

Amanieu (Mar 01 2020 at 17:45, on Zulip):

@nagisa Actually sideeffect is an attribute on the asm, while readnone is an attribute on the call instruction that invokes the asm. So they don't actually interact in LLVM.

nagisa (Mar 01 2020 at 17:45, on Zulip):

readonly sideeffect being optimised out sounds like a bug.

Amanieu (Mar 01 2020 at 17:46, on Zulip):

sideeffect is only actually looked at deep in the backend. By then the call asm has already been optimized away.

nagisa (Mar 01 2020 at 17:48, on Zulip):

I didn’t look much at the asm's sideeffect annotation, but the sideeffect intrinsic does interact with the readnone etc attributes very much. In particular sideeffect prevents LLVM from inferring a readnone attribute where it otherwise would. But if readnone is already specified somewhere, that takes precedence.

nagisa (Mar 01 2020 at 17:48, on Zulip):

And readnone is exactly what makes LLVM to delete things it considers to be dead code.

nagisa (Mar 01 2020 at 17:49, on Zulip):

(this most likely applies to readonly the same way)

Amanieu (Mar 01 2020 at 17:49, on Zulip):

I think we should use inaccessiblememonly instead of readnone for non-pure asm with nomem. That tells LLVM that the asm doesn't touch any LLVM-visible memory, but still has some significant side-effect.

nagisa (Mar 01 2020 at 17:52, on Zulip):

I wouldn't add readnone attribute at all and let LLVM infer it. inaccessiblememonly or inaccessiblemem_or_argmemonly sound like saner choices.

Amanieu (Mar 01 2020 at 17:53, on Zulip):

LLVM can't infer it because it can't read the asm.

Amanieu (Mar 01 2020 at 17:53, on Zulip):

Clang uses readnone/readonly only for non-volatile asm.

nagisa (Mar 01 2020 at 17:54, on Zulip):

Well… I guess. I don’t remember the RFC well enough to contribute to the discussion much here.

Amanieu (Mar 01 2020 at 18:05, on Zulip):

Hmm I think I'm going to go with option b: pure must be used with either nomem or readonly, otherwise error. And I will relax the rules of pure to allow reading from memory when used with readonly.

Amanieu (Mar 01 2020 at 18:08, on Zulip):

So that leaves 4 valid combinations:

Amanieu (Mar 01 2020 at 18:09, on Zulip):

Which lower to:

Lokathor (Mar 01 2020 at 18:28, on Zulip):

what do writes count as? the "nothing" category?

nagisa (Mar 01 2020 at 18:30, on Zulip):

Lokathor said:

what do writes count as? the "nothing" category?

I believe the default plain asm! without annotations is the conservative thing and will allow arbitrary things (including writes)

Amanieu (Mar 01 2020 at 18:33, on Zulip):

Sorry 5 combinations, the last one being no attributes, which also corresponds to (nothing)

Amanieu (Mar 01 2020 at 18:33, on Zulip):

LLVM doesn't have any attributes to represent inaccessiblemem_or_readonly, so we have to be conservative for readonly without pure.

Last update: Apr 03 2020 at 18:20UTC