stoat icon indicating copy to clipboard operation
stoat copied to clipboard

Use trivial data-dependencies to ignore non-rt functions with trivial conditionals

Open falkTX opened this issue 8 years ago • 3 comments

Note sure how to title this.

Take the following code: https://github.com/falkTX/Carla/blob/01b50d2f0ba44f4e98e2ae75082a0a465116d9ef/source/backend/plugin/CarlaPlugin.cpp#L1306 There's 2 boolean arguments - sendOsc and sendCallback. This function is called from RT side, but with those arguments as false. For example here: https://github.com/falkTX/Carla/blob/01b50d2f0ba44f4e98e2ae75082a0a465116d9ef/source/backend/plugin/CarlaPluginLADSPA.cpp#L968

Hopefully it's possible to detect the cases where the code obviously is not being run, like calling a function with 'false' directly, as in the examples. Carla's stoat output is 75% filled with stuff like this.

falkTX avatar Jan 17 '18 10:01 falkTX

One of the issues with stoat (documented at LAC) is that it does not use any data dependent information to determine if a function will be called.

For example if you have the function:

void a(void) {
  if(0)
    b();
}

Then stoat will (to the best of my knowledge) report that a can possibly call b as clang is called with -O0.

The above case is fairly easy to handle with a few of LLVM's optimization passes, though optimization operations make it a fair bit harder to reason about the original code. The case that you're interested in is a harder one however as you want to be able to propagate a constant through a function call. As to why this is difficult let's look at the minimum test example:

void a(void) { }

void b(int c)
{
    if(c)
        a();
}

void d(void) { b(1); }

void e(void) { b(0); }

Translated to LLVM IR this looks like:

; ModuleID = '<stdin>'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

; Function Attrs: nounwind uwtable
define void @a() #0 {
  ret void
}

; Function Attrs: nounwind uwtable
define void @b(i32 %c) #0 {
  %1 = alloca i32, align 4
  store i32 %c, i32* %1, align 4
  %2 = load i32, i32* %1, align 4
  %3 = icmp ne i32 %2, 0
  br i1 %3, label %4, label %5

; <label>:4                                       ; preds = %0
  call void @a()
  br label %5

; <label>:5                                       ; preds = %4, %0
  ret void
}

; Function Attrs: nounwind uwtable
define void @d() #0 {
  call void @b(i32 1)
  ret void
}

; Function Attrs: nounwind uwtable
define void @e() #0 {
  call void @b(i32 0)
  ret void
}

attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.ident = !{!0}

!0 = !{!"clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)"}

To use the data dependency within function b(), we must look at the branch above <label>:4 . From there we need to establish if %3 is true/false. Next we need to invert the logic about %2 to say that 0== no branch, then a few more steps have to trace the value back to being an argument.

Expanding this to across functions, then there needs to be a new node in the stoat graph which is a specialization of b() whenever there's a 0 argument. With that established then there likely needs to be another pass over all calls of b() to determine if they're b(special-case) or b(unknown-case). Then it's possible to say that e calls b_specialization0 rather than just b().

So the feature request is certainly doable, but a non-trivial bit of work. My current suggestion is to have separate functions for realtime and non-realtime operations, though I realize that this may not always be a possibility. In those cases a suppression would be useful.

fundamental avatar Jan 17 '18 18:01 fundamental

hmm I see. would it be possible to add a decorator/attribute for functions that can be called like this? that would mean only selected functions will need to go through the special argument verification

falkTX avatar Jan 17 '18 21:01 falkTX

An attribute doesn't save that much time/effort IMO. Most of the work is in the complexity of implementing the feature, not the time spent executing the feature after it's implemented.

fundamental avatar Jan 17 '18 21:01 fundamental