[llvm-dev] [RFC] A new intrinsic, `llvm.blackbox`, to explicitly prevent constprop, die, etc optimizations

Diego Novillo via llvm-dev llvm-dev at lists.llvm.org
Tue Nov 3 12:50:56 PST 2015


I don't see how this is any different from volatile markers on loads/stores
or memory barriers or several other optimizer blocking devices.  They
generally end up crippling the optimizers without much added benefit.

Would it be possible to stop the code motion you want to block by
explicitly exposing data dependencies?  Or simply disabling some
optimizations with pragmas?


Diego.

On Mon, Nov 2, 2015 at 6:57 PM, Richard Diamond via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> Hey all,
>
> I'd like to propose a new intrinsic for use in preventing optimizations
> from deleting IR due to constant propagation, dead code elimination, etc.
>
>
> # Background/Motivation
>
> In Rust we have a crate called `test` which provides a function,
> `black_box`, which is designed to be a no-op function that prevents
> constprop, die, etc from interfering with tests/benchmarks but otherwise
> doesn't negatively affect resulting machine code quality. `test` currently
> implements this function by using inline asm, which marks a pointer to the
> argument as used by the assembly.
>
> At the IR level, this creates an alloca, stores it's argument to it, calls
> the no-op inline asm with the alloca pointer, and then returns a load of
> the alloca. Obviously, `mem2reg` would normally optimize this sort of
> pattern away, however the deliberate use of the no-op asm prevents other
> desirable optimizations (such as the aforementioned `mem2reg` pass) a
> little too well.
>
> Existing and upcoming virtual ISA targets also don't have this luxury
> (PNaCl/JS and WebAssembly, respectively). For these kind of targets, Rust's
> `test` currently forbids inlining of `black_box`, which crudely achieves
> the same effect. This is undesirable for any target because of the
> associated call overhead.
>
> The IR for `test::black_box::<i32>` is currently (it gets inlined, as
> desired, so I've omitted the function signature):
>
> ````llvm
>   %dummy.i = alloca i32, align 4
>   %2 = bitcast i32* %dummy.i to i8*
>   call void @llvm.lifetime.start(i64 4, i8* %2) #1
> ; Here, the value operand was the original argument to
> `test::black_box::<i32>`
>   store i32 2, i32* %dummy.i, align 4
>   call void asm "", "r,~{dirflag},~{fpsr},~{flags}"(i32* %dummy.i) #1,
> !srcloc !0
>   %3 = load i32, i32* %dummy.i, align 4
>   call void @llvm.lifetime.end(i64 4, i8* %2) #1
> ````
>
> This could be better.
>
> # Solution
>
> Add a new intrinsic, called `llvm.blackbox`, which accepts a value of any
> type and returns a value of the same type. As with many other intrinsics,
> this intrinsic shall remain unknown to all optimizations, before and during
> codegen. Specifically, this intrinsic should prevent all optimizations
> which operate by assuming properties of the value passed to the intrinsic.
> Once the last optimization pass (of any kind) is finished, all calls can be
> RAUW its argument.
>
> Table-gen def:
>
> ```tablegen
> def int_blackbox : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>]>;
> ```
>
> Thus, using the previous example, `%3` would become:
> ```llvm
>   %3 = call i32 @llvm.blackbox.i32(i32 2)
>
> ```
>
> #
>
> Thoughts and suggestions welcome.
>
> Thanks,
> Richard Diamond
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151103/16fbd9f3/attachment.html>


More information about the llvm-dev mailing list