<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<div class="moz-cite-prefix">On 10/10/2018 4:27 PM, Taylor Cramer
via llvm-dev wrote:<br>
</div>
<blockquote type="cite"
cite="mid:CAFVyvB+jPNenhgBB_=8Uov6bvyZM6ZpNy07L0qy4-xD6mvf-Ow@mail.gmail.com">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<div dir="ltr">The <a
href="https://llvm.org/docs/LangRef.html#volatile-memory-accesses"
target="_blank" moz-do-not-send="true">language reference</a> says
that <span class="gmail-il">LLVM</span> optimizers must not
change the number of volatile operations or change their order
of execution relative to other volatile operations. However, it
doesn't say that optimizers can't introduce non-volatile
operations. Is there any way to write IR that would ensure the
generated loads and stores exactly match the number and ordering
of the loads and stores in the source IR? I've heard conflicting
reports about this. I'm specifically interested in manipulating
MMIO, where loads and stores may have side effects.
<div>
<div><br>
</div>
<div>If it is in fact possible to prevent the insertion of
loads/stores, does the presence of the "dereferenceable"
attribute on pointers have any affect here? Will marking a
pointer "dereferenceable" allow loads/stores to a
volatile-only-accessed memory location that wouldn't be
allowed otherwise?</div>
</div>
<div><br>
</div>
<div>Context: this discussion originated in <a
href="https://github.com/rust-rfcs/unsafe-code-guidelines/issues/33"
target="_blank" moz-do-not-send="true">an issue on the Rust
unsafe code guidelines issue tracker</a>.</div>
</div>
</blockquote>
<br>
<a class="moz-txt-link-freetext" href="http://llvm.org/docs/LangRef.html#pointer-aliasing-rules">http://llvm.org/docs/LangRef.html#pointer-aliasing-rules</a> says "Any
memory access must be done through a pointer value associated with
an address range of the memory access, otherwise the behavior is
undefined."<br>
<br>
From LLVM's perspective, we can refer to all the memory which can
possibly be accessed according to those rules as "allocated
memory". A non-volatile memory access can only access allocated
memory. MMIO registers are not allocated memory; they do not behave
the way LLVM expects memory to behave. So a non-volatile load from
an MMIO register has undefined behavior. And a pointer marked
dereferenceable cannot point to an MMIO register, or the behavior is
undefined.<br>
<br>
volatile accesses are special; they have target-specific semantics,
so they can access MMIO registers even though that isn't allowed for
a non-volatile load.<br>
<br>
In practice, this means your code will do what you want as long as
all MMIO accesses are volatile.<br>
<br>
-Eli
<pre class="moz-signature" cols="72">--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project</pre>
</body>
</html>