; RUN: opt -S -always-inline < %s | FileCheck %s declare void @f() declare i32 @g() declare fastcc i32 @g.fastcc() define i32 @callee_0() alwaysinline { entry: call void @f() ret i32 2 } define i32 @caller_0() { ; CHECK-LABEL: @caller_0( entry: ; CHECK: entry: ; CHECK-NEXT: call void @f() ; CHECK-NEXT: ret i32 2 %x = call i32 @callee_0() [ "deopt"(i32 5) ] ret i32 %x } define i32 @callee_1() alwaysinline { entry: call void @f() [ "deopt"() ] call void @f() [ "deopt"(i32 0, i32 1) ] call void @f() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] ret i32 2 } define i32 @caller_1() { ; CHECK-LABEL: @caller_1( entry: ; CHECK: entry: ; CHECK-NEXT: call void @f() [ "deopt"(i32 5) ] ; CHECK-NEXT: call void @f() [ "deopt"(i32 5, i32 0, i32 1) ] ; CHECK-NEXT: call void @f() [ "deopt"(i32 5, i32 0, i32 1), "foo"(double 0.000000e+00) ] ; CHECK-NEXT: ret i32 2 %x = call i32 @callee_1() [ "deopt"(i32 5) ] ret i32 %x } define i32 @callee_2() alwaysinline { entry: %v = call i32 @g() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] ret i32 %v } define i32 @caller_2(i32 %val) { ; CHECK-LABEL: @caller_2( entry: ; CHECK: entry: ; CHECK-NEXT: [[RVAL:%[^ ]+]] = call i32 @g() [ "deopt"(i32 %val, i32 0, i32 1), "foo"(double 0.000000e+00) ] ; CHECK-NEXT: ret i32 [[RVAL]] %x = call i32 @callee_2() [ "deopt"(i32 %val) ] ret i32 %x } define i32 @callee_3() alwaysinline { entry: %v = call i32 @g() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] ret i32 %v } define i32 @caller_3() personality i8 3 { ; CHECK-LABEL: @caller_3( entry: %x = invoke i32 @callee_3() [ "deopt"(i32 7) ] to label %normal unwind label %unwind ; CHECK: invoke i32 @g() [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ] normal: ret i32 %x unwind: %cleanup = landingpad i8 cleanup ret i32 101 } define i32 @callee_4() alwaysinline personality i8 3 { entry: %v = invoke i32 @g() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] to label %normal unwind label %unwind normal: ret i32 %v unwind: %cleanup = landingpad i8 cleanup ret i32 100 } define i32 @caller_4() { ; CHECK-LABEL: @caller_4( entry: ; CHECK: invoke i32 @g() [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ] %x = call i32 @callee_4() [ "deopt"(i32 7) ] ret i32 %x } define i32 @callee_5() alwaysinline personality i8 3 { entry: %v = invoke fastcc i32 @g.fastcc() #0 [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] to label %normal unwind label %unwind normal: ret i32 %v unwind: %cleanup = landingpad i8 cleanup ret i32 100 } define i32 @caller_5() { ; CHECK-LABEL: @caller_5( entry: ; CHECK: invoke fastcc i32 @g.fastcc() #[[FOO_BAR_ATTR_IDX:[0-9]+]] [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ] %x = call i32 @callee_5() [ "deopt"(i32 7) ] ret i32 %x } define i32 @callee_6() alwaysinline personality i8 3 { entry: %v = call fastcc i32 @g.fastcc() #0 [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] ret i32 %v } define i32 @caller_6() { ; CHECK-LABEL: @caller_6( entry: ; CHECK: call fastcc i32 @g.fastcc() #[[FOO_BAR_ATTR_IDX]] [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ] %x = call i32 @callee_6() [ "deopt"(i32 7) ] ret i32 %x } define i32 @callee_7(i1 %val) alwaysinline personality i8 3 { ; We want something that PruningFunctionCloner is not smart enough to ; recognize, but can be recognized by recursivelySimplifyInstruction. entry: br i1 %val, label %check, label %precheck precheck: br label %check check: %p = phi i1 [ %val, %entry ], [ true, %precheck ] br i1 %p, label %do.not, label %do do.not: ret i32 0 do: %v = call fastcc i32 @g.fastcc() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] ret i32 %v } define i32 @caller_7() { ; CHECK-LABEL: @caller_7( entry: ; CHECK-NOT: call fastcc i32 @g.fastcc() ; CHECK: ret i32 0 %x = call i32 @callee_7(i1 true) [ "deopt"(i32 7) ] ret i32 %x } define i32 @callee_8(i1 %val) alwaysinline personality i8 3 { ; We want something that PruningFunctionCloner is not smart enough to ; recognize, but can be recognized by recursivelySimplifyInstruction. entry: br i1 %val, label %check, label %precheck precheck: br label %check check: %p = phi i1 [ %val, %entry ], [ true, %precheck ] br i1 %p, label %do.not, label %do do.not: ret i32 0 do: %phi = phi i32 [ 0, %check ], [ %v, %do ] %v = call fastcc i32 @g.fastcc() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] %ic = icmp eq i32 %v, 42 br i1 %ic, label %do, label %done done: ret i32 %phi } define i32 @caller_8() { ; CHECK-LABEL: @caller_8( entry: ; CHECK-NOT: call fastcc i32 @g.fastcc() ; CHECK: ret i32 0 %x = call i32 @callee_8(i1 true) [ "deopt"(i32 7) ] ret i32 %x } attributes #0 = { "foo"="bar" } ; CHECK: attributes #[[FOO_BAR_ATTR_IDX]] = { "foo"="bar" }