
This adds support for specialising recursive functions. For example: int Global = 1; void recursiveFunc(int *arg) { if (*arg < 4) { print(*arg); recursiveFunc(*arg + 1); } } void main() { recursiveFunc(&Global); } After 3 iterations of function specialisation, followed by inlining of the specialised versions of recursiveFunc, the main function looks like this: void main() { print(1); print(2); print(3); } To support this, the following has been added: - Update the solver and state of the new specialised functions, - An optimisation to propagate constant stack values after each iteration of function specialisation, which is necessary for the next iteration to recognise the constant values and trigger. Specialising recursive functions is (at the moment) controlled by option -func-specialization-max-iters and is opt-in for compile-time reasons. I.e., the default is -func-specialization-max-iters=1, but for the example above we would need to use -func-specialization-max-iters=3. Future work is to see if we can increase the default, or improve the cost-model/heuristics to control compile-times. Differential Revision: https://reviews.llvm.org/D106426
35 lines
905 B
LLVM
35 lines
905 B
LLVM
; RUN: opt -function-specialization -force-function-specialization -func-specialization-max-iters=2 -S < %s | FileCheck %s
|
|
|
|
; Duplicate store preventing recursive specialisation:
|
|
;
|
|
; CHECK: @recursiveFunc.1
|
|
; CHECK-NOT: @recursiveFunc.2
|
|
|
|
@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, 4
|
|
br i1 %arg.cmp, label %block6, label %ret.block
|
|
|
|
block6:
|
|
call void @print_val(i32 %arg.load)
|
|
%arg.add = add nsw i32 %arg.load, 1
|
|
store i32 %arg.add, i32* %temp, align 4
|
|
store i32 %arg.add, i32* %temp, align 4
|
|
call void @recursiveFunc(i32* nonnull %temp)
|
|
br 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)
|