1; The inliner should never inline recursive functions into other functions. 2; This effectively is just peeling off the first iteration of a loop, and the 3; inliner heuristics are not set up for this. 4 5; RUN: opt -inline -S < %s | FileCheck %s 6; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s 7 8target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 9target triple = "x86_64-apple-darwin10.3" 10 11@g = common global i32 0 ; <i32*> [#uses=1] 12 13define internal void @foo(i32 %x) nounwind ssp { 14entry: 15 %0 = icmp slt i32 %x, 0 ; <i1> [#uses=1] 16 br i1 %0, label %return, label %bb 17 18bb: ; preds = %entry 19 %1 = sub nsw i32 %x, 1 ; <i32> [#uses=1] 20 call void @foo(i32 %1) nounwind ssp 21 store volatile i32 1, i32* @g, align 4 22 ret void 23 24return: ; preds = %entry 25 ret void 26} 27 28 29;; CHECK-LABEL: @bonk( 30;; CHECK: call void @foo(i32 42) 31define void @bonk() nounwind ssp { 32entry: 33 call void @foo(i32 42) nounwind ssp 34 ret void 35} 36 37 38 39;; Here is an indirect case that should not be infinitely inlined. 40 41define internal void @f1(i32 %x, i8* %Foo, i8* %Bar) nounwind ssp { 42entry: 43 %0 = bitcast i8* %Bar to void (i32, i8*, i8*)* 44 %1 = sub nsw i32 %x, 1 45 call void %0(i32 %1, i8* %Foo, i8* %Bar) nounwind 46 store volatile i32 42, i32* @g, align 4 47 ret void 48} 49 50define internal void @f2(i32 %x, i8* %Foo, i8* %Bar) nounwind ssp { 51entry: 52 %0 = icmp slt i32 %x, 0 ; <i1> [#uses=1] 53 br i1 %0, label %return, label %bb 54 55bb: ; preds = %entry 56 %1 = bitcast i8* %Foo to void (i32, i8*, i8*)* ; <void (i32, i8*, i8*)*> [#uses=1] 57 call void %1(i32 %x, i8* %Foo, i8* %Bar) nounwind 58 store volatile i32 13, i32* @g, align 4 59 ret void 60 61return: ; preds = %entry 62 ret void 63} 64 65 66; CHECK-LABEL: @top_level( 67; CHECK: call void @f2(i32 122 68; Here we inline one instance of the cycle, but we don't want to completely 69; unroll it. 70define void @top_level() nounwind ssp { 71entry: 72 call void @f2(i32 123, i8* bitcast (void (i32, i8*, i8*)* @f1 to i8*), i8* bitcast (void (i32, i8*, i8*)* @f2 to i8*)) nounwind ssp 73 ret void 74} 75 76 77; Check that a recursive function, when called with a constant that makes the 78; recursive path dead code can actually be inlined. 79define i32 @fib(i32 %i) { 80entry: 81 %is.zero = icmp eq i32 %i, 0 82 br i1 %is.zero, label %zero.then, label %zero.else 83 84zero.then: 85 ret i32 0 86 87zero.else: 88 %is.one = icmp eq i32 %i, 1 89 br i1 %is.one, label %one.then, label %one.else 90 91one.then: 92 ret i32 1 93 94one.else: 95 %i1 = sub i32 %i, 1 96 %f1 = call i32 @fib(i32 %i1) 97 %i2 = sub i32 %i, 2 98 %f2 = call i32 @fib(i32 %i2) 99 %f = add i32 %f1, %f2 100 ret i32 %f 101} 102 103define i32 @fib_caller() { 104; CHECK-LABEL: @fib_caller( 105; CHECK-NOT: call 106; CHECK: ret 107 %f1 = call i32 @fib(i32 0) 108 %f2 = call i32 @fib(i32 1) 109 %result = add i32 %f1, %f2 110 ret i32 %result 111} 112