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

Jeroen Dobbelaere via llvm-dev llvm-dev at lists.llvm.org
Tue Nov 10 02:04:21 PST 2015


Hi Richard,

why don't you use an inline assembly that returns your argument in a register ?

For example:
----

int foo(int a, int b)
{
  int c=a+b+10;
  __asm__ volatile ("":"=r"(c):"0"(c):"memory");

  return c+20;
}
---


results in: (Note that the +10 and +20 were not combined)

---
foo:                                    # @foo
        .cfi_startproc
# BB#0:
        leal    10(%rdi,%rsi), %eax
        #APP
        #NO_APP
        addl    $20, %eax
        retq
.Lfunc_end0:
        .size   foo, .Lfunc_end0-foo
        .cfi_endproc
--

At llvm-ir level, it looks like:

---
define i32 @foo(i32 %a, i32 %b) #0 {
  %1 = add i32 %a, 10
  %2 = add i32 %1, %b
  %3 = tail call i32 asm sideeffect "", "=r,0,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 %2) #1, !srcloc !1
  %4 = add nsw i32 %3, 20
  ret i32 %4
}
---

Greetings,

Jeroen Dobbelaere



From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of Richard Diamond via llvm-dev
Sent: Tuesday, November 03, 2015 12:58 AM
To: llvm-dev at lists.llvm.org
Subject: [llvm-dev] [RFC] A new intrinsic, `llvm.blackbox`, to explicitly prevent constprop, die, etc optimizations

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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151110/7cf35b2f/attachment.html>


More information about the llvm-dev mailing list