[PATCH] D106426: [FuncSpec] Support specialising recursive functions

Chuanqi Xu via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 27 01:40:24 PDT 2021


ChuanqiXu added a comment.

In D106426#2906622 <https://reviews.llvm.org/D106426#2906622>, @SjoerdMeijer wrote:

> In D106426#2906213 <https://reviews.llvm.org/D106426#2906213>, @ChuanqiXu wrote:
>
>> 4 times is an arbitrary number. I thought the best would be 1 time only. But I worried if it is too strict. So I said 4 times. Now I think we should be more strict. So I think it would better to specialize it only 1 time.
>
> I can't follow any this. There are only arbitrary numbers here. I can't follow the decision making behind this, because no rationale is given.
> Taking your example, specialising 4 times, and after cleanup passes like inline, instcombine, and simplify cfg, this would exactly give the code I would expect.
> And that's the problem of this discussion, it is based on a idea, and not based on an any data that we can verify. For *this* example, I don't see which high level criteria is the problem:
>
> - compile-times,
> - code-size,
> - performance.
>
>>> how things work for recursive function, I think we need to discuss how the cost-model changes would look like
>>
>> I think we need to handle recursive function specially. Since it is common that recursive function f  and its specialized one f' have the same cost and bonus. We need to record the function specialized (and specialized argument). Then we need to specialize a function (for specific argument) we had specialized, we could forbid it or give it a much higher penalty. The detail is missing. But the key point is that we need to handle recursive function specially instead of tuning or refactoring the cost model.
>
> To help this discussion and make this concrete, can you take your own example, and point exactly on what code-generation criteria I mentioned before you would like to specialise this only once?
>
> The problem I have with this discussion is that it is based on an idea that I cannot verify with data. While I understand the general idea, perhaps, and implementing a penalty is easy but I simply don't know what that should be. I can put a random/arbitrary number in, but why would we do that? That's why I still prefer the approach of getting this foundation in place, because it is opt-in, then we can tune this further.

Hi, for this example:

  ; opt -function-specialization -func-specialization-max-iters=100  -S %s
  @Global = internal constant i32 1, align 4
  
  define internal void @recursiveFunc(i32* nocapture readonly %arg) {
    %temp = alloca i32, align 4
    %arg.load = load i32, i32* %arg, align 4
    %arg.cmp = icmp slt i32 %arg.load, 10000
    br i1 %arg.cmp, label %loop1, label %ret.block
  
  loop1:
    br label %loop2
  
  loop2:
    br label %loop3
  
  loop3:
    br label %loop4
  
  loop4:
    br label %block6
  
  block6:
    call void @print_val(i32 %arg.load)
    %arg.add = add nsw i32 %arg.load, 1
    store i32 %arg.add, i32* %temp, align 4
    call void @recursiveFunc(i32* nonnull %temp)
    br label %loop4.end
  
  loop4.end:
    %exit_cond1 = call i1 @exit_cond()
    br i1 %exit_cond1, label %loop4, label %loop3.end
  
  loop3.end:
    %exit_cond2 = call i1 @exit_cond()
    br i1 %exit_cond2, label %loop3, label %loop2.end
  
  loop2.end:
    %exit_cond3 = call i1 @exit_cond()
    br i1 %exit_cond3, label %loop2, label %loop1.end
  
  loop1.end:
    %exit_cond4 = call i1 @exit_cond()
    br i1 %exit_cond4, label %loop1, label %ret.block
  
  ret.block:
    ret void
  }
  
  define i32 @main() {
    call void @recursiveFunc(i32* nonnull @Global)
    ret i32 0
  }
  
  declare dso_local void @print_val(i32)
  declare dso_local i1 @exit_cond()

If we run `bin/opt -function-specialization -func-specialization-max-iters=10  -S %s`, we could find that `recursiveFunc` would get specialized 18 times. But I believe it would be a consensus for us that `recursiveFunc ` shouldn't get specialized so many times.
Then I run `bin/opt -function-specialization -func-specialization-max-iters=10 -inline -instcombine -simplifycfg -S %s`, I got:

  ; ModuleID = 'RecursiveFunc.ll'
  source_filename = "RecursiveFunc.ll"
  
  @Global = internal constant i32 1, align 4
  @funcspec.arg = internal constant i32 2
  @funcspec.arg.3 = internal constant i32 3
  @funcspec.arg.5 = internal constant i32 4
  @funcspec.arg.7 = internal constant i32 5
  @funcspec.arg.9 = internal constant i32 6
  @funcspec.arg.11 = internal constant i32 7
  @funcspec.arg.13 = internal constant i32 8
  @funcspec.arg.15 = internal constant i32 9
  @funcspec.arg.17 = internal constant i32 10
  @funcspec.arg.19 = internal constant i32 11
  
  define internal void @recursiveFunc(i32* nocapture readonly %arg) {
    %temp = alloca i32, align 4
    %arg.load = load i32, i32* %arg, align 4
    %arg.cmp = icmp slt i32 %arg.load, 10000
    br i1 %arg.cmp, label %loop1, label %ret.block
  
  loop1:                                            ; preds = %loop1.end, %0
    br label %loop2
  
  loop2:                                            ; preds = %loop2.end, %loop1
    br label %loop3
  
  loop3:                                            ; preds = %loop3.end, %loop2
    br label %loop4
  
  loop4:                                            ; preds = %loop4, %loop3
    call void @print_val(i32 %arg.load)
    %arg.add = add nsw i32 %arg.load, 1
    store i32 %arg.add, i32* %temp, align 4
    call void @recursiveFunc(i32* nonnull %temp)
    %exit_cond1 = call i1 @exit_cond()
    br i1 %exit_cond1, label %loop4, label %loop3.end
  
  loop3.end:                                        ; preds = %loop4
    %exit_cond2 = call i1 @exit_cond()
    br i1 %exit_cond2, label %loop3, label %loop2.end
  
  loop2.end:                                        ; preds = %loop3.end
    %exit_cond3 = call i1 @exit_cond()
    br i1 %exit_cond3, label %loop2, label %loop1.end
  
  loop1.end:                                        ; preds = %loop2.end
    %exit_cond4 = call i1 @exit_cond()
    br i1 %exit_cond4, label %loop1, label %ret.block
  
  ret.block:                                        ; preds = %loop1.end, %0
    ret void
  }
  
  define i32 @main() {
    br label %loop1.i
  
  loop1.i:                                          ; preds = %loop1.end.i, %0
    br label %loop2.i
  
  loop2.i:                                          ; preds = %loop2.end.i, %loop1.i
    br label %loop3.i
  
  loop3.i:                                          ; preds = %loop3.end.i, %loop2.i
    br label %loop4.i
  
  loop4.i:                                          ; preds = %recursiveFunc.2.exit.i, %loop3.i
    call void @print_val(i32 1)
    br label %loop1.i.i
  
  loop1.i.i:                                        ; preds = %loop1.end.i.i, %loop4.i
    br label %loop2.i.i
  
  loop2.i.i:                                        ; preds = %loop2.end.i.i, %loop1.i.i
    br label %loop3.i.i
  
  loop3.i.i:                                        ; preds = %loop3.end.i.i, %loop2.i.i
    br label %loop4.i.i
  
  loop4.i.i:                                        ; preds = %recursiveFunc.4.exit.i.i, %loop3.i.i
    call void @print_val(i32 2)
    br label %loop1.i.i.i
  
  loop1.i.i.i:                                      ; preds = %loop1.end.i.i.i, %loop4.i.i
    br label %loop2.i.i.i
  
  loop2.i.i.i:                                      ; preds = %loop2.end.i.i.i, %loop1.i.i.i
    br label %loop3.i.i.i
  
  loop3.i.i.i:                                      ; preds = %loop3.end.i.i.i, %loop2.i.i.i
    br label %loop4.i.i.i
  
  loop4.i.i.i:                                      ; preds = %recursiveFunc.6.exit.i.i.i, %loop3.i.i.i
    call void @print_val(i32 3)
    br label %loop1.i.i.i.i
  
  loop1.i.i.i.i:                                    ; preds = %loop1.end.i.i.i.i, %loop4.i.i.i
    br label %loop2.i.i.i.i
  
  loop2.i.i.i.i:                                    ; preds = %loop2.end.i.i.i.i, %loop1.i.i.i.i
    br label %loop3.i.i.i.i
  
  loop3.i.i.i.i:                                    ; preds = %loop3.end.i.i.i.i, %loop2.i.i.i.i
    br label %loop4.i.i.i.i
  
  loop4.i.i.i.i:                                    ; preds = %recursiveFunc.8.exit.i.i.i.i, %loop3.i.i.i.i
    call void @print_val(i32 4)
    br label %loop1.i.i.i.i.i
  
  loop1.i.i.i.i.i:                                  ; preds = %loop1.end.i.i.i.i.i, %loop4.i.i.i.i
    br label %loop2.i.i.i.i.i
  
  loop2.i.i.i.i.i:                                  ; preds = %loop2.end.i.i.i.i.i, %loop1.i.i.i.i.i
    br label %loop3.i.i.i.i.i
  
  loop3.i.i.i.i.i:                                  ; preds = %loop3.end.i.i.i.i.i, %loop2.i.i.i.i.i
    br label %loop4.i.i.i.i.i
  
  loop4.i.i.i.i.i:                                  ; preds = %recursiveFunc.10.exit.i.i.i.i.i, %loop3.i.i.i.i.i
    call void @print_val(i32 5)
    br label %loop1.i.i.i.i.i.i
  
  loop1.i.i.i.i.i.i:                                ; preds = %loop1.end.i.i.i.i.i.i, %loop4.i.i.i.i.i
    br label %loop2.i.i.i.i.i.i
  
  loop2.i.i.i.i.i.i:                                ; preds = %loop2.end.i.i.i.i.i.i, %loop1.i.i.i.i.i.i
    br label %loop3.i.i.i.i.i.i
  
  loop3.i.i.i.i.i.i:                                ; preds = %loop3.end.i.i.i.i.i.i, %loop2.i.i.i.i.i.i
    br label %loop4.i.i.i.i.i.i
  
  loop4.i.i.i.i.i.i:                                ; preds = %recursiveFunc.12.exit.i.i.i.i.i.i, %loop3.i.i.i.i.i.i
    call void @print_val(i32 6)
    br label %loop1.i.i.i.i.i.i.i
  
  loop1.i.i.i.i.i.i.i:                              ; preds = %loop1.end.i.i.i.i.i.i.i, %loop4.i.i.i.i.i.i
    br label %loop2.i.i.i.i.i.i.i
  
  loop2.i.i.i.i.i.i.i:                              ; preds = %loop2.end.i.i.i.i.i.i.i, %loop1.i.i.i.i.i.i.i
    br label %loop3.i.i.i.i.i.i.i
  
  loop3.i.i.i.i.i.i.i:                              ; preds = %loop3.end.i.i.i.i.i.i.i, %loop2.i.i.i.i.i.i.i
    br label %loop4.i.i.i.i.i.i.i
  
  loop4.i.i.i.i.i.i.i:                              ; preds = %recursiveFunc.14.exit.i.i.i.i.i.i.i, %loop3.i.i.i.i.i.i.i
    call void @print_val(i32 7)
    br label %loop1.i.i.i.i.i.i.i.i
  
  loop1.i.i.i.i.i.i.i.i:                            ; preds = %loop1.end.i.i.i.i.i.i.i.i, %loop4.i.i.i.i.i.i.i
    br label %loop2.i.i.i.i.i.i.i.i
  
  loop2.i.i.i.i.i.i.i.i:                            ; preds = %loop2.end.i.i.i.i.i.i.i.i, %loop1.i.i.i.i.i.i.i.i
    br label %loop3.i.i.i.i.i.i.i.i
  
  loop3.i.i.i.i.i.i.i.i:                            ; preds = %loop3.end.i.i.i.i.i.i.i.i, %loop2.i.i.i.i.i.i.i.i
    br label %loop4.i.i.i.i.i.i.i.i
  
  loop4.i.i.i.i.i.i.i.i:                            ; preds = %recursiveFunc.16.exit.i.i.i.i.i.i.i.i, %loop3.i.i.i.i.i.i.i.i
    call void @print_val(i32 8)
    br label %loop1.i.i.i.i.i.i.i.i.i
  
  loop1.i.i.i.i.i.i.i.i.i:                          ; preds = %loop1.end.i.i.i.i.i.i.i.i.i, %loop4.i.i.i.i.i.i.i.i
    br label %loop2.i.i.i.i.i.i.i.i.i
  
  loop2.i.i.i.i.i.i.i.i.i:                          ; preds = %loop2.end.i.i.i.i.i.i.i.i.i, %loop1.i.i.i.i.i.i.i.i.i
    br label %loop3.i.i.i.i.i.i.i.i.i
  
  loop3.i.i.i.i.i.i.i.i.i:                          ; preds = %loop3.end.i.i.i.i.i.i.i.i.i, %loop2.i.i.i.i.i.i.i.i.i
    br label %loop4.i.i.i.i.i.i.i.i.i
  
  loop4.i.i.i.i.i.i.i.i.i:                          ; preds = %recursiveFunc.18.exit.i.i.i.i.i.i.i.i.i, %loop3.i.i.i.i.i.i.i.i.i
    call void @print_val(i32 9)
    br label %loop1.i.i.i.i.i.i.i.i.i.i
  
  loop1.i.i.i.i.i.i.i.i.i.i:                        ; preds = %loop1.end.i.i.i.i.i.i.i.i.i.i, %loop4.i.i.i.i.i.i.i.i.i
    br label %loop2.i.i.i.i.i.i.i.i.i.i
  
  loop2.i.i.i.i.i.i.i.i.i.i:                        ; preds = %loop2.end.i.i.i.i.i.i.i.i.i.i, %loop1.i.i.i.i.i.i.i.i.i.i
    br label %loop3.i.i.i.i.i.i.i.i.i.i
  
  loop3.i.i.i.i.i.i.i.i.i.i:                        ; preds = %loop3.end.i.i.i.i.i.i.i.i.i.i, %loop2.i.i.i.i.i.i.i.i.i.i
    br label %loop4.i.i.i.i.i.i.i.i.i.i
  
  loop4.i.i.i.i.i.i.i.i.i.i:                        ; preds = %loop4.i.i.i.i.i.i.i.i.i.i, %loop3.i.i.i.i.i.i.i.i.i.i
    call void @print_val(i32 10)
    call void @recursiveFunc(i32* nonnull @funcspec.arg.19)
    %exit_cond1.i.i.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond1.i.i.i.i.i.i.i.i.i.i, label %loop4.i.i.i.i.i.i.i.i.i.i, label %loop3.end.i.i.i.i.i.i.i.i.i.i
  
  loop3.end.i.i.i.i.i.i.i.i.i.i:                    ; preds = %loop4.i.i.i.i.i.i.i.i.i.i
    %exit_cond2.i.i.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond2.i.i.i.i.i.i.i.i.i.i, label %loop3.i.i.i.i.i.i.i.i.i.i, label %loop2.end.i.i.i.i.i.i.i.i.i.i
  
  loop2.end.i.i.i.i.i.i.i.i.i.i:                    ; preds = %loop3.end.i.i.i.i.i.i.i.i.i.i
    %exit_cond3.i.i.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond3.i.i.i.i.i.i.i.i.i.i, label %loop2.i.i.i.i.i.i.i.i.i.i, label %loop1.end.i.i.i.i.i.i.i.i.i.i
  
  loop1.end.i.i.i.i.i.i.i.i.i.i:                    ; preds = %loop2.end.i.i.i.i.i.i.i.i.i.i
    %exit_cond4.i.i.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond4.i.i.i.i.i.i.i.i.i.i, label %loop1.i.i.i.i.i.i.i.i.i.i, label %recursiveFunc.18.exit.i.i.i.i.i.i.i.i.i
  
  recursiveFunc.18.exit.i.i.i.i.i.i.i.i.i:          ; preds = %loop1.end.i.i.i.i.i.i.i.i.i.i
    %exit_cond1.i.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond1.i.i.i.i.i.i.i.i.i, label %loop4.i.i.i.i.i.i.i.i.i, label %loop3.end.i.i.i.i.i.i.i.i.i
  
  loop3.end.i.i.i.i.i.i.i.i.i:                      ; preds = %recursiveFunc.18.exit.i.i.i.i.i.i.i.i.i
    %exit_cond2.i.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond2.i.i.i.i.i.i.i.i.i, label %loop3.i.i.i.i.i.i.i.i.i, label %loop2.end.i.i.i.i.i.i.i.i.i
  
  loop2.end.i.i.i.i.i.i.i.i.i:                      ; preds = %loop3.end.i.i.i.i.i.i.i.i.i
    %exit_cond3.i.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond3.i.i.i.i.i.i.i.i.i, label %loop2.i.i.i.i.i.i.i.i.i, label %loop1.end.i.i.i.i.i.i.i.i.i
  
  loop1.end.i.i.i.i.i.i.i.i.i:                      ; preds = %loop2.end.i.i.i.i.i.i.i.i.i
    %exit_cond4.i.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond4.i.i.i.i.i.i.i.i.i, label %loop1.i.i.i.i.i.i.i.i.i, label %recursiveFunc.16.exit.i.i.i.i.i.i.i.i
  
  recursiveFunc.16.exit.i.i.i.i.i.i.i.i:            ; preds = %loop1.end.i.i.i.i.i.i.i.i.i
    %exit_cond1.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond1.i.i.i.i.i.i.i.i, label %loop4.i.i.i.i.i.i.i.i, label %loop3.end.i.i.i.i.i.i.i.i
  
  loop3.end.i.i.i.i.i.i.i.i:                        ; preds = %recursiveFunc.16.exit.i.i.i.i.i.i.i.i
    %exit_cond2.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond2.i.i.i.i.i.i.i.i, label %loop3.i.i.i.i.i.i.i.i, label %loop2.end.i.i.i.i.i.i.i.i
  
  loop2.end.i.i.i.i.i.i.i.i:                        ; preds = %loop3.end.i.i.i.i.i.i.i.i
    %exit_cond3.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond3.i.i.i.i.i.i.i.i, label %loop2.i.i.i.i.i.i.i.i, label %loop1.end.i.i.i.i.i.i.i.i
  
  loop1.end.i.i.i.i.i.i.i.i:                        ; preds = %loop2.end.i.i.i.i.i.i.i.i
    %exit_cond4.i.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond4.i.i.i.i.i.i.i.i, label %loop1.i.i.i.i.i.i.i.i, label %recursiveFunc.14.exit.i.i.i.i.i.i.i
  
  recursiveFunc.14.exit.i.i.i.i.i.i.i:              ; preds = %loop1.end.i.i.i.i.i.i.i.i
    %exit_cond1.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond1.i.i.i.i.i.i.i, label %loop4.i.i.i.i.i.i.i, label %loop3.end.i.i.i.i.i.i.i
  
  loop3.end.i.i.i.i.i.i.i:                          ; preds = %recursiveFunc.14.exit.i.i.i.i.i.i.i
    %exit_cond2.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond2.i.i.i.i.i.i.i, label %loop3.i.i.i.i.i.i.i, label %loop2.end.i.i.i.i.i.i.i
  
  loop2.end.i.i.i.i.i.i.i:                          ; preds = %loop3.end.i.i.i.i.i.i.i
    %exit_cond3.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond3.i.i.i.i.i.i.i, label %loop2.i.i.i.i.i.i.i, label %loop1.end.i.i.i.i.i.i.i
  
  loop1.end.i.i.i.i.i.i.i:                          ; preds = %loop2.end.i.i.i.i.i.i.i
    %exit_cond4.i.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond4.i.i.i.i.i.i.i, label %loop1.i.i.i.i.i.i.i, label %recursiveFunc.12.exit.i.i.i.i.i.i
  
  recursiveFunc.12.exit.i.i.i.i.i.i:                ; preds = %loop1.end.i.i.i.i.i.i.i
    %exit_cond1.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond1.i.i.i.i.i.i, label %loop4.i.i.i.i.i.i, label %loop3.end.i.i.i.i.i.i
  
  loop3.end.i.i.i.i.i.i:                            ; preds = %recursiveFunc.12.exit.i.i.i.i.i.i
    %exit_cond2.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond2.i.i.i.i.i.i, label %loop3.i.i.i.i.i.i, label %loop2.end.i.i.i.i.i.i
  
  loop2.end.i.i.i.i.i.i:                            ; preds = %loop3.end.i.i.i.i.i.i
    %exit_cond3.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond3.i.i.i.i.i.i, label %loop2.i.i.i.i.i.i, label %loop1.end.i.i.i.i.i.i
  
  loop1.end.i.i.i.i.i.i:                            ; preds = %loop2.end.i.i.i.i.i.i
    %exit_cond4.i.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond4.i.i.i.i.i.i, label %loop1.i.i.i.i.i.i, label %recursiveFunc.10.exit.i.i.i.i.i
  
  recursiveFunc.10.exit.i.i.i.i.i:                  ; preds = %loop1.end.i.i.i.i.i.i
    %exit_cond1.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond1.i.i.i.i.i, label %loop4.i.i.i.i.i, label %loop3.end.i.i.i.i.i
  
  loop3.end.i.i.i.i.i:                              ; preds = %recursiveFunc.10.exit.i.i.i.i.i
    %exit_cond2.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond2.i.i.i.i.i, label %loop3.i.i.i.i.i, label %loop2.end.i.i.i.i.i
  
  loop2.end.i.i.i.i.i:                              ; preds = %loop3.end.i.i.i.i.i
    %exit_cond3.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond3.i.i.i.i.i, label %loop2.i.i.i.i.i, label %loop1.end.i.i.i.i.i
  
  loop1.end.i.i.i.i.i:                              ; preds = %loop2.end.i.i.i.i.i
    %exit_cond4.i.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond4.i.i.i.i.i, label %loop1.i.i.i.i.i, label %recursiveFunc.8.exit.i.i.i.i
  
  recursiveFunc.8.exit.i.i.i.i:                     ; preds = %loop1.end.i.i.i.i.i
    %exit_cond1.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond1.i.i.i.i, label %loop4.i.i.i.i, label %loop3.end.i.i.i.i
  
  loop3.end.i.i.i.i:                                ; preds = %recursiveFunc.8.exit.i.i.i.i
    %exit_cond2.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond2.i.i.i.i, label %loop3.i.i.i.i, label %loop2.end.i.i.i.i
  
  loop2.end.i.i.i.i:                                ; preds = %loop3.end.i.i.i.i
    %exit_cond3.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond3.i.i.i.i, label %loop2.i.i.i.i, label %loop1.end.i.i.i.i
  
  loop1.end.i.i.i.i:                                ; preds = %loop2.end.i.i.i.i
    %exit_cond4.i.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond4.i.i.i.i, label %loop1.i.i.i.i, label %recursiveFunc.6.exit.i.i.i
  
  recursiveFunc.6.exit.i.i.i:                       ; preds = %loop1.end.i.i.i.i
    %exit_cond1.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond1.i.i.i, label %loop4.i.i.i, label %loop3.end.i.i.i
  
  loop3.end.i.i.i:                                  ; preds = %recursiveFunc.6.exit.i.i.i
    %exit_cond2.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond2.i.i.i, label %loop3.i.i.i, label %loop2.end.i.i.i
  
  loop2.end.i.i.i:                                  ; preds = %loop3.end.i.i.i
    %exit_cond3.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond3.i.i.i, label %loop2.i.i.i, label %loop1.end.i.i.i
  
  loop1.end.i.i.i:                                  ; preds = %loop2.end.i.i.i
    %exit_cond4.i.i.i = call i1 @exit_cond()
    br i1 %exit_cond4.i.i.i, label %loop1.i.i.i, label %recursiveFunc.4.exit.i.i
  
  recursiveFunc.4.exit.i.i:                         ; preds = %loop1.end.i.i.i
    %exit_cond1.i.i = call i1 @exit_cond()
    br i1 %exit_cond1.i.i, label %loop4.i.i, label %loop3.end.i.i
  
  loop3.end.i.i:                                    ; preds = %recursiveFunc.4.exit.i.i
    %exit_cond2.i.i = call i1 @exit_cond()
    br i1 %exit_cond2.i.i, label %loop3.i.i, label %loop2.end.i.i
  
  loop2.end.i.i:                                    ; preds = %loop3.end.i.i
    %exit_cond3.i.i = call i1 @exit_cond()
    br i1 %exit_cond3.i.i, label %loop2.i.i, label %loop1.end.i.i
  
  loop1.end.i.i:                                    ; preds = %loop2.end.i.i
    %exit_cond4.i.i = call i1 @exit_cond()
    br i1 %exit_cond4.i.i, label %loop1.i.i, label %recursiveFunc.2.exit.i
  
  recursiveFunc.2.exit.i:                           ; preds = %loop1.end.i.i
    %exit_cond1.i = call i1 @exit_cond()
    br i1 %exit_cond1.i, label %loop4.i, label %loop3.end.i
  
  loop3.end.i:                                      ; preds = %recursiveFunc.2.exit.i
    %exit_cond2.i = call i1 @exit_cond()
    br i1 %exit_cond2.i, label %loop3.i, label %loop2.end.i
  
  loop2.end.i:                                      ; preds = %loop3.end.i
    %exit_cond3.i = call i1 @exit_cond()
    br i1 %exit_cond3.i, label %loop2.i, label %loop1.end.i
  
  loop1.end.i:                                      ; preds = %loop2.end.i
    %exit_cond4.i = call i1 @exit_cond()
    br i1 %exit_cond4.i, label %loop1.i, label %recursiveFunc.1.exit
  
  recursiveFunc.1.exit:                             ; preds = %loop1.end.i
    ret i32 0
  }
  
  declare dso_local void @print_val(i32)
  
  declare dso_local i1 @exit_cond()
  
  ; Function Attrs: argmemonly nofree nosync nounwind willreturn
  declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #0
  
  ; Function Attrs: argmemonly nofree nosync nounwind willreturn
  declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #0
  
  attributes #0 = { argmemonly nofree nosync nounwind willreturn }

hmmmm, I guess it must not be your expected code, right?

> For *this* example, I don't see which high level criteria is the problem:
> compile-times,
> code-size,
> performance.

I think all of them would be affected. The impact on code-size is obvious. For the compile-time, it would take a long time to compile if we set the argument  `func-specialization-max-iters` to 2000.

> That's why I still prefer the approach of getting this foundation in place, because it is opt-in, then we can tune this further.

I prefer to use small program to analysis. My work flow to optimize would be :

  Run big workloads -> analysis the hot part -> extract small example from the hot part -> optimize for the hot part -> prove the effects with the big workloads. 

It is hard to optimize big workloads directly since many details are missing. So I think it may be better to talk about the small example if we can. I mean, we need to take many time to find a small program from workloads to find the insight generally. But if we could talk about the small example directly, it would be much better.

> I can't follow any this. There are only arbitrary numbers here. I can't follow the decision making behind this, because no rationale is given.

My bad. I mean we shouldn't make `recursiveFunc` arbitrarily. The limit number may get discussed more.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106426/new/

https://reviews.llvm.org/D106426



More information about the llvm-commits mailing list