[PATCH] D106426: [FuncSpec] Support specialising recursive functions
Sjoerd Meijer via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 23 07:21:23 PDT 2021
SjoerdMeijer added a comment.
Thanks for elaborating on this!
See my comments inline.
In D106426#2899586 <https://reviews.llvm.org/D106426#2899586>, @ChuanqiXu wrote:
> Let me give a more formal description.
> (1) Call the set of new generated functions in i-th iteration with `Fs[i]`, and `Fs[0]` would be the set of functions initially. And the number of functions generated in i-th iterations would be `|Fs[i]|`.
> (2) The penalty to specialize a function would be `Penalty(F) * NumSpecialized[i]`. `NumSpecialized[i]` would be `Fs[1] + Fs[2] + ... + Fs[I]`.
> (3) The bonus to specialize a function would be `Bonus(F, ArgNo)`. For normal recursive function `F` and the specialized one `SF`, it's normal that `Bonus(F, ArgNo) == Bonus(SF, ArgNo)` and `Penalty(F) == Penalty(SF)`. It means that `SF` may be specialized again if `NumSpecialized[I]` may not be large enough.
>
> Then we could find that now the total number of specialized function would be controlled by `NumSpecialized` which increases linearly.
100% agreed so far. This is indeed how things work at the moment to recursively/linearly specialise recursive functions.
> But here is the problem that the implementation `Bonus(F, ArgNo)` would increase exponentially with the depth of loops. It shows that we may get in trouble if we met a recursive function with a deep loop.
> And the things we want to do is to add the iteration time `I` to the cost model of `Penalty(F, i)`.
Ok, thanks, I am going to look into this!
> For 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()
>
> I guess I would be happy if `recursiveFunc ` would get specialized less than 4 times even when we set `func-specialization-max-iters` to 100.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D106426/new/
https://reviews.llvm.org/D106426
More information about the llvm-commits
mailing list