|  | ; RUN: opt < %s -inline -inline-threshold=20 -S | FileCheck %s | 
|  | ; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=20 -S | FileCheck %s | 
|  |  | 
|  | define internal i32 @callee1(i32 %A, i32 %B) { | 
|  | %C = sdiv i32 %A, %B | 
|  | ret i32 %C | 
|  | } | 
|  |  | 
|  | define i32 @caller1() { | 
|  | ; CHECK-LABEL: define i32 @caller1( | 
|  | ; CHECK-NEXT: ret i32 3 | 
|  |  | 
|  | %X = call i32 @callee1( i32 10, i32 3 ) | 
|  | ret i32 %X | 
|  | } | 
|  |  | 
|  | define i32 @caller2() { | 
|  | ; Check that we can constant-prop through instructions after inlining callee21 | 
|  | ; to get constants in the inlined callsite to callee22. | 
|  | ; FIXME: Currently, the threshold is fixed at 20 because we don't perform | 
|  | ; *recursive* cost analysis to realize that the nested call site will definitely | 
|  | ; inline and be cheap. We should eventually do that and lower the threshold here | 
|  | ; to 1. | 
|  | ; | 
|  | ; CHECK-LABEL: @caller2( | 
|  | ; CHECK-NOT: call void @callee2 | 
|  | ; CHECK: ret | 
|  |  | 
|  | %x = call i32 @callee21(i32 42, i32 48) | 
|  | ret i32 %x | 
|  | } | 
|  |  | 
|  | define i32 @callee21(i32 %x, i32 %y) { | 
|  | %sub = sub i32 %y, %x | 
|  | %result = call i32 @callee22(i32 %sub) | 
|  | ret i32 %result | 
|  | } | 
|  |  | 
|  | declare i8* @getptr() | 
|  |  | 
|  | define i32 @callee22(i32 %x) { | 
|  | %icmp = icmp ugt i32 %x, 42 | 
|  | br i1 %icmp, label %bb.true, label %bb.false | 
|  | bb.true: | 
|  | ; This block musn't be counted in the inline cost. | 
|  | %x1 = add i32 %x, 1 | 
|  | %x2 = add i32 %x1, 1 | 
|  | %x3 = add i32 %x2, 1 | 
|  | %x4 = add i32 %x3, 1 | 
|  | %x5 = add i32 %x4, 1 | 
|  | %x6 = add i32 %x5, 1 | 
|  | %x7 = add i32 %x6, 1 | 
|  | %x8 = add i32 %x7, 1 | 
|  |  | 
|  | ret i32 %x8 | 
|  | bb.false: | 
|  | ret i32 %x | 
|  | } | 
|  |  | 
|  | define i32 @caller3() { | 
|  | ; Check that even if the expensive path is hidden behind several basic blocks, | 
|  | ; it doesn't count toward the inline cost when constant-prop proves those paths | 
|  | ; dead. | 
|  | ; | 
|  | ; CHECK-LABEL: @caller3( | 
|  | ; CHECK-NOT: call | 
|  | ; CHECK: ret i32 6 | 
|  |  | 
|  | entry: | 
|  | %x = call i32 @callee3(i32 42, i32 48) | 
|  | ret i32 %x | 
|  | } | 
|  |  | 
|  | define i32 @callee3(i32 %x, i32 %y) { | 
|  | %sub = sub i32 %y, %x | 
|  | %icmp = icmp ugt i32 %sub, 42 | 
|  | br i1 %icmp, label %bb.true, label %bb.false | 
|  |  | 
|  | bb.true: | 
|  | %icmp2 = icmp ult i32 %sub, 64 | 
|  | br i1 %icmp2, label %bb.true.true, label %bb.true.false | 
|  |  | 
|  | bb.true.true: | 
|  | ; This block musn't be counted in the inline cost. | 
|  | %x1 = add i32 %x, 1 | 
|  | %x2 = add i32 %x1, 1 | 
|  | %x3 = add i32 %x2, 1 | 
|  | %x4 = add i32 %x3, 1 | 
|  | %x5 = add i32 %x4, 1 | 
|  | %x6 = add i32 %x5, 1 | 
|  | %x7 = add i32 %x6, 1 | 
|  | %x8 = add i32 %x7, 1 | 
|  | br label %bb.merge | 
|  |  | 
|  | bb.true.false: | 
|  | ; This block musn't be counted in the inline cost. | 
|  | %y1 = add i32 %y, 1 | 
|  | %y2 = add i32 %y1, 1 | 
|  | %y3 = add i32 %y2, 1 | 
|  | %y4 = add i32 %y3, 1 | 
|  | %y5 = add i32 %y4, 1 | 
|  | %y6 = add i32 %y5, 1 | 
|  | %y7 = add i32 %y6, 1 | 
|  | %y8 = add i32 %y7, 1 | 
|  | br label %bb.merge | 
|  |  | 
|  | bb.merge: | 
|  | %result = phi i32 [ %x8, %bb.true.true ], [ %y8, %bb.true.false ] | 
|  | ret i32 %result | 
|  |  | 
|  | bb.false: | 
|  | ret i32 %sub | 
|  | } | 
|  |  | 
|  | declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b) | 
|  |  | 
|  | define i8 @caller4(i8 %z) { | 
|  | ; Check that we can constant fold through intrinsics such as the | 
|  | ; overflow-detecting arithmetic instrinsics. These are particularly important | 
|  | ; as they are used heavily in standard library code and generic C++ code where | 
|  | ; the arguments are oftent constant but complete generality is required. | 
|  | ; | 
|  | ; CHECK-LABEL: @caller4( | 
|  | ; CHECK-NOT: call | 
|  | ; CHECK: ret i8 -1 | 
|  |  | 
|  | entry: | 
|  | %x = call i8 @callee4(i8 254, i8 14, i8 %z) | 
|  | ret i8 %x | 
|  | } | 
|  |  | 
|  | define i8 @callee4(i8 %x, i8 %y, i8 %z) { | 
|  | %uadd = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %x, i8 %y) | 
|  | %o = extractvalue {i8, i1} %uadd, 1 | 
|  | br i1 %o, label %bb.true, label %bb.false | 
|  |  | 
|  | bb.true: | 
|  | ret i8 -1 | 
|  |  | 
|  | bb.false: | 
|  | ; This block musn't be counted in the inline cost. | 
|  | %z1 = add i8 %z, 1 | 
|  | %z2 = add i8 %z1, 1 | 
|  | %z3 = add i8 %z2, 1 | 
|  | %z4 = add i8 %z3, 1 | 
|  | %z5 = add i8 %z4, 1 | 
|  | %z6 = add i8 %z5, 1 | 
|  | %z7 = add i8 %z6, 1 | 
|  | %z8 = add i8 %z7, 1 | 
|  | ret i8 %z8 | 
|  | } | 
|  |  | 
|  | define i64 @caller5(i64 %y) { | 
|  | ; Check that we can round trip constants through various kinds of casts etc w/o | 
|  | ; losing track of the constant prop in the inline cost analysis. | 
|  | ; | 
|  | ; CHECK-LABEL: @caller5( | 
|  | ; CHECK-NOT: call | 
|  | ; CHECK: ret i64 -1 | 
|  |  | 
|  | entry: | 
|  | %x = call i64 @callee5(i64 42, i64 %y) | 
|  | ret i64 %x | 
|  | } | 
|  |  | 
|  | define i64 @callee5(i64 %x, i64 %y) { | 
|  | %inttoptr = inttoptr i64 %x to i8* | 
|  | %bitcast = bitcast i8* %inttoptr to i32* | 
|  | %ptrtoint = ptrtoint i32* %bitcast to i64 | 
|  | %trunc = trunc i64 %ptrtoint to i32 | 
|  | %zext = zext i32 %trunc to i64 | 
|  | %cmp = icmp eq i64 %zext, 42 | 
|  | br i1 %cmp, label %bb.true, label %bb.false | 
|  |  | 
|  | bb.true: | 
|  | ret i64 -1 | 
|  |  | 
|  | bb.false: | 
|  | ; This block musn't be counted in the inline cost. | 
|  | %y1 = add i64 %y, 1 | 
|  | %y2 = add i64 %y1, 1 | 
|  | %y3 = add i64 %y2, 1 | 
|  | %y4 = add i64 %y3, 1 | 
|  | %y5 = add i64 %y4, 1 | 
|  | %y6 = add i64 %y5, 1 | 
|  | %y7 = add i64 %y6, 1 | 
|  | %y8 = add i64 %y7, 1 | 
|  | ret i64 %y8 | 
|  | } | 
|  |  | 
|  | define float @caller6() { | 
|  | ; Check that we can constant-prop through fcmp instructions | 
|  | ; | 
|  | ; CHECK-LABEL: @caller6( | 
|  | ; CHECK-NOT: call | 
|  | ; CHECK: ret | 
|  | %x = call float @callee6(float 42.0) | 
|  | ret float %x | 
|  | } | 
|  |  | 
|  | define float @callee6(float %x) { | 
|  | %icmp = fcmp ugt float %x, 42.0 | 
|  | br i1 %icmp, label %bb.true, label %bb.false | 
|  |  | 
|  | bb.true: | 
|  | ; This block musn't be counted in the inline cost. | 
|  | %x1 = fadd float %x, 1.0 | 
|  | %x2 = fadd float %x1, 1.0 | 
|  | %x3 = fadd float %x2, 1.0 | 
|  | %x4 = fadd float %x3, 1.0 | 
|  | %x5 = fadd float %x4, 1.0 | 
|  | %x6 = fadd float %x5, 1.0 | 
|  | %x7 = fadd float %x6, 1.0 | 
|  | %x8 = fadd float %x7, 1.0 | 
|  | ret float %x8 | 
|  |  | 
|  | bb.false: | 
|  | ret float %x | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | define i32 @PR13412.main() { | 
|  | ; This is a somewhat complicated three layer subprogram that was reported to | 
|  | ; compute the wrong value for a branch due to assuming that an argument | 
|  | ; mid-inline couldn't be equal to another pointer. | 
|  | ; | 
|  | ; After inlining, the branch should point directly to the exit block, not to | 
|  | ; the intermediate block. | 
|  | ; CHECK: @PR13412.main | 
|  | ; CHECK: br i1 true, label %[[TRUE_DEST:.*]], label %[[FALSE_DEST:.*]] | 
|  | ; CHECK: [[FALSE_DEST]]: | 
|  | ; CHECK-NEXT: call void @PR13412.fail() | 
|  | ; CHECK: [[TRUE_DEST]]: | 
|  | ; CHECK-NEXT: ret i32 0 | 
|  |  | 
|  | entry: | 
|  | %i1 = alloca i64 | 
|  | store i64 0, i64* %i1 | 
|  | %arraydecay = bitcast i64* %i1 to i32* | 
|  | %call = call i1 @PR13412.first(i32* %arraydecay, i32* %arraydecay) | 
|  | br i1 %call, label %cond.end, label %cond.false | 
|  |  | 
|  | cond.false: | 
|  | call void @PR13412.fail() | 
|  | br label %cond.end | 
|  |  | 
|  | cond.end: | 
|  | ret i32 0 | 
|  | } | 
|  |  | 
|  | define internal i1 @PR13412.first(i32* %a, i32* %b) { | 
|  | entry: | 
|  | %call = call i32* @PR13412.second(i32* %a, i32* %b) | 
|  | %cmp = icmp eq i32* %call, %b | 
|  | ret i1 %cmp | 
|  | } | 
|  |  | 
|  | declare void @PR13412.fail() | 
|  |  | 
|  | define internal i32* @PR13412.second(i32* %a, i32* %b) { | 
|  | entry: | 
|  | %sub.ptr.lhs.cast = ptrtoint i32* %b to i64 | 
|  | %sub.ptr.rhs.cast = ptrtoint i32* %a to i64 | 
|  | %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast | 
|  | %sub.ptr.div = ashr exact i64 %sub.ptr.sub, 2 | 
|  | %cmp = icmp ugt i64 %sub.ptr.div, 1 | 
|  | br i1 %cmp, label %if.then, label %if.end3 | 
|  |  | 
|  | if.then: | 
|  | %0 = load i32, i32* %a | 
|  | %1 = load i32, i32* %b | 
|  | %cmp1 = icmp eq i32 %0, %1 | 
|  | br i1 %cmp1, label %return, label %if.end3 | 
|  |  | 
|  | if.end3: | 
|  | br label %return | 
|  |  | 
|  | return: | 
|  | %retval.0 = phi i32* [ %b, %if.end3 ], [ %a, %if.then ] | 
|  | ret i32* %retval.0 | 
|  | } | 
|  |  | 
|  | declare i32 @PR28802.external(i32 returned %p1) | 
|  |  | 
|  | define internal i32 @PR28802.callee() { | 
|  | entry: | 
|  | br label %cont | 
|  |  | 
|  | cont: | 
|  | %0 = phi i32 [ 0, %entry ] | 
|  | %call = call i32 @PR28802.external(i32 %0) | 
|  | ret i32 %call | 
|  | } | 
|  |  | 
|  | define i32 @PR28802() { | 
|  | entry: | 
|  | %call = call i32 @PR28802.callee() | 
|  | ret i32 %call | 
|  | } | 
|  |  | 
|  | ; CHECK-LABEL: define i32 @PR28802( | 
|  | ; CHECK: %[[call:.*]] = call i32 @PR28802.external(i32 0) | 
|  | ; CHECK: ret i32 %[[call]] | 
|  |  | 
|  | define internal i32 @PR28848.callee(i32 %p2, i1 %c) { | 
|  | entry: | 
|  | br i1 %c, label %cond.end, label %cond.true | 
|  |  | 
|  | cond.true: | 
|  | br label %cond.end | 
|  |  | 
|  | cond.end: | 
|  | %cond = phi i32 [ 0, %cond.true ], [ %p2, %entry ] | 
|  | %or = or i32 %cond, %p2 | 
|  | ret i32 %or | 
|  | } | 
|  |  | 
|  | define i32 @PR28848() { | 
|  | entry: | 
|  | %call = call i32 @PR28848.callee(i32 0, i1 false) | 
|  | ret i32 %call | 
|  | } | 
|  | ; CHECK-LABEL: define i32 @PR28848( | 
|  | ; CHECK: ret i32 0 | 
|  |  | 
|  | define internal void @callee7(i16 %param1, i16 %param2) { | 
|  | entry: | 
|  | br label %bb | 
|  |  | 
|  | bb: | 
|  | %phi = phi i16 [ %param2, %entry ] | 
|  | %add = add i16 %phi, %param1 | 
|  | ret void | 
|  | } | 
|  |  | 
|  | declare i16 @caller7.external(i16 returned) | 
|  |  | 
|  | define void @caller7() { | 
|  | bb1: | 
|  | %call = call i16 @caller7.external(i16 1) | 
|  | call void @callee7(i16 0, i16 %call) | 
|  | ret void | 
|  | } | 
|  | ; CHECK-LABEL: define void @caller7( | 
|  | ; CHECK: %call = call i16 @caller7.external(i16 1) | 
|  | ; CHECK-NEXT: ret void |