1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -S -passes=inline %s | FileCheck %s 3; RUN: opt -S -passes='cgscc(inline)' %s | FileCheck %s 4; RUN: opt -S -passes='module-inline' %s | FileCheck %s 5 6declare void @foo() 7declare void @bar() 8 9define void @callee(ptr %arg) { 10; CHECK-LABEL: define void @callee 11; CHECK-SAME: (ptr [[ARG:%.*]]) { 12; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[ARG]], null 13; CHECK-NEXT: br i1 [[CMP]], label [[EXPENSIVE:%.*]], label [[DONE:%.*]] 14; CHECK: expensive: 15; CHECK-NEXT: call void @foo() 16; CHECK-NEXT: call void @foo() 17; CHECK-NEXT: call void @foo() 18; CHECK-NEXT: call void @foo() 19; CHECK-NEXT: call void @foo() 20; CHECK-NEXT: call void @foo() 21; CHECK-NEXT: call void @foo() 22; CHECK-NEXT: call void @foo() 23; CHECK-NEXT: call void @foo() 24; CHECK-NEXT: call void @foo() 25; CHECK-NEXT: ret void 26; CHECK: done: 27; CHECK-NEXT: call void @bar() 28; CHECK-NEXT: ret void 29; 30 %cmp = icmp eq ptr %arg, null 31 br i1 %cmp, label %expensive, label %done 32 33; This block is designed to be too expensive to inline. We can only inline 34; callee if this block is known to be dead. 35expensive: 36 call void @foo() 37 call void @foo() 38 call void @foo() 39 call void @foo() 40 call void @foo() 41 call void @foo() 42 call void @foo() 43 call void @foo() 44 call void @foo() 45 call void @foo() 46 ret void 47 48done: 49 call void @bar() 50 ret void 51} 52 53; Positive test - arg is known non null 54define void @caller(ptr nonnull %arg) { 55; CHECK-LABEL: define void @caller 56; CHECK-SAME: (ptr nonnull [[ARG:%.*]]) { 57; CHECK-NEXT: call void @bar() 58; CHECK-NEXT: ret void 59; 60 call void @callee(ptr nonnull %arg) 61 ret void 62} 63 64; Negative test - arg is not known to be non null 65define void @caller2(ptr %arg) { 66; CHECK-LABEL: define void @caller2 67; CHECK-SAME: (ptr [[ARG:%.*]]) { 68; CHECK-NEXT: call void @callee(ptr [[ARG]]) 69; CHECK-NEXT: ret void 70; 71 call void @callee(ptr %arg) 72 ret void 73} 74 75define void @caller3(ptr %arg) { 76; CHECK-LABEL: define void @caller3 77; CHECK-SAME: (ptr [[ARG:%.*]]) { 78; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[ARG]], null 79; CHECK-NEXT: br i1 [[CMP_I]], label [[EXPENSIVE_I:%.*]], label [[DONE_I:%.*]] 80; CHECK: expensive.i: 81; CHECK-NEXT: call void @foo() 82; CHECK-NEXT: call void @foo() 83; CHECK-NEXT: call void @foo() 84; CHECK-NEXT: call void @foo() 85; CHECK-NEXT: call void @foo() 86; CHECK-NEXT: call void @foo() 87; CHECK-NEXT: call void @foo() 88; CHECK-NEXT: call void @foo() 89; CHECK-NEXT: call void @foo() 90; CHECK-NEXT: call void @foo() 91; CHECK-NEXT: br label [[CALLEE_EXIT:%.*]] 92; CHECK: done.i: 93; CHECK-NEXT: call void @bar() 94; CHECK-NEXT: br label [[CALLEE_EXIT]] 95; CHECK: callee.exit: 96; CHECK-NEXT: ret void 97; 98 call void @callee(ptr nonnull %arg) 99 ret void 100} 101 102define void @caller4(ptr dereferenceable(8) %arg) { 103; CHECK-LABEL: define void @caller4 104; CHECK-SAME: (ptr dereferenceable(8) [[ARG:%.*]]) { 105; CHECK-NEXT: call void @callee(ptr dereferenceable(8) [[ARG]]) 106; CHECK-NEXT: ret void 107; 108 call void @callee(ptr dereferenceable(8) %arg) 109 ret void 110} 111 112define void @caller5(ptr dereferenceable(8) %arg) { 113; CHECK-LABEL: define void @caller5 114; CHECK-SAME: (ptr dereferenceable(8) [[ARG:%.*]]) { 115; CHECK-NEXT: call void @callee(ptr [[ARG]]) 116; CHECK-NEXT: ret void 117; 118 call void @callee(ptr %arg) 119 ret void 120} 121 122define void @caller6(ptr %arg) { 123; CHECK-LABEL: define void @caller6 124; CHECK-SAME: (ptr [[ARG:%.*]]) { 125; CHECK-NEXT: call void @callee(ptr dereferenceable(8) [[ARG]]) 126; CHECK-NEXT: ret void 127; 128 call void @callee(ptr dereferenceable(8) %arg) 129 ret void 130} 131 132declare ptr @buz() 133define nonnull ptr @callee7() { 134; CHECK-LABEL: define nonnull ptr @callee7() { 135; CHECK-NEXT: [[R:%.*]] = call ptr @buz() #[[ATTR0:[0-9]+]] 136; CHECK-NEXT: ret ptr [[R]] 137; 138 %r = call ptr @buz() willreturn nounwind 139 ret ptr %r 140} 141 142define ptr @caller7() { 143; CHECK-LABEL: define ptr @caller7() { 144; CHECK-NEXT: [[R_I:%.*]] = call nonnull ptr @buz() #[[ATTR0]] 145; CHECK-NEXT: ret ptr [[R_I]] 146; 147 %r = call ptr @callee7() 148 ret ptr %r 149} 150 151define nonnull ptr @callee8() { 152; CHECK-LABEL: define nonnull ptr @callee8() { 153; CHECK-NEXT: [[R:%.*]] = call ptr @buz() 154; CHECK-NEXT: ret ptr [[R]] 155; 156 %r = call ptr @buz() 157 ret ptr %r 158} 159 160define ptr @caller8() { 161; CHECK-LABEL: define ptr @caller8() { 162; CHECK-NEXT: [[R_I:%.*]] = call nonnull ptr @buz() 163; CHECK-NEXT: ret ptr [[R_I]] 164; 165 %r = call nonnull ptr @callee8() 166 ret ptr %r 167} 168 169define ptr @callee9() { 170; CHECK-LABEL: define ptr @callee9() { 171; CHECK-NEXT: [[R:%.*]] = call ptr @buz() 172; CHECK-NEXT: call void @foo() #[[ATTR1:[0-9]+]] 173; CHECK-NEXT: ret ptr [[R]] 174; 175 %r = call ptr @buz() 176 call void @foo() nounwind 177 ret ptr %r 178} 179 180define ptr @caller9() { 181; CHECK-LABEL: define ptr @caller9() { 182; CHECK-NEXT: [[R_I:%.*]] = call ptr @buz() 183; CHECK-NEXT: call void @foo() #[[ATTR1]] 184; CHECK-NEXT: ret ptr [[R_I]] 185; 186 %r = call nonnull ptr @callee9() 187 ret ptr %r 188} 189