1 ; RUN: opt -S -always-inline < %s | FileCheck %s 2 3 declare void @f() 4 declare i32 @g() 5 declare fastcc i32 @g.fastcc() 6 7 define i32 @callee_0() alwaysinline { 8 entry: 9 call void @f() 10 ret i32 2 11 } 12 13 define i32 @caller_0() { 14 ; CHECK-LABEL: @caller_0( 15 entry: 16 ; CHECK: entry: 17 ; CHECK-NEXT: call void @f() 18 ; CHECK-NEXT: ret i32 2 19 %x = call i32 @callee_0() [ "deopt"(i32 5) ] 20 ret i32 %x 21 } 22 23 define i32 @callee_1() alwaysinline { 24 entry: 25 call void @f() [ "deopt"() ] 26 call void @f() [ "deopt"(i32 0, i32 1) ] 27 call void @f() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] 28 ret i32 2 29 } 30 31 define i32 @caller_1() { 32 ; CHECK-LABEL: @caller_1( 33 entry: 34 ; CHECK: entry: 35 ; CHECK-NEXT: call void @f() [ "deopt"(i32 5) ] 36 ; CHECK-NEXT: call void @f() [ "deopt"(i32 5, i32 0, i32 1) ] 37 ; CHECK-NEXT: call void @f() [ "deopt"(i32 5, i32 0, i32 1), "foo"(double 0.000000e+00) ] 38 ; CHECK-NEXT: ret i32 2 39 40 %x = call i32 @callee_1() [ "deopt"(i32 5) ] 41 ret i32 %x 42 } 43 44 define i32 @callee_2() alwaysinline { 45 entry: 46 %v = call i32 @g() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] 47 ret i32 %v 48 } 49 50 define i32 @caller_2(i32 %val) { 51 ; CHECK-LABEL: @caller_2( 52 entry: 53 ; CHECK: entry: 54 ; CHECK-NEXT: [[RVAL:%[^ ]+]] = call i32 @g() [ "deopt"(i32 %val, i32 0, i32 1), "foo"(double 0.000000e+00) ] 55 ; CHECK-NEXT: ret i32 [[RVAL]] 56 %x = call i32 @callee_2() [ "deopt"(i32 %val) ] 57 ret i32 %x 58 } 59 60 define i32 @callee_3() alwaysinline { 61 entry: 62 %v = call i32 @g() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] 63 ret i32 %v 64 } 65 66 define i32 @caller_3() personality i8 3 { 67 ; CHECK-LABEL: @caller_3( 68 entry: 69 %x = invoke i32 @callee_3() [ "deopt"(i32 7) ] to label %normal unwind label %unwind 70 ; CHECK: invoke i32 @g() [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ] 71 72 normal: 73 ret i32 %x 74 75 unwind: 76 %cleanup = landingpad i8 cleanup 77 ret i32 101 78 } 79 80 define i32 @callee_4() alwaysinline personality i8 3 { 81 entry: 82 %v = invoke i32 @g() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] to label %normal unwind label %unwind 83 84 normal: 85 ret i32 %v 86 87 unwind: 88 %cleanup = landingpad i8 cleanup 89 ret i32 100 90 } 91 92 define i32 @caller_4() { 93 ; CHECK-LABEL: @caller_4( 94 entry: 95 ; CHECK: invoke i32 @g() [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ] 96 %x = call i32 @callee_4() [ "deopt"(i32 7) ] 97 ret i32 %x 98 } 99 100 define i32 @callee_5() alwaysinline personality i8 3 { 101 entry: 102 %v = invoke fastcc i32 @g.fastcc() #0 [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] to label %normal unwind label %unwind 103 104 normal: 105 ret i32 %v 106 107 unwind: 108 %cleanup = landingpad i8 cleanup 109 ret i32 100 110 } 111 112 define i32 @caller_5() { 113 ; CHECK-LABEL: @caller_5( 114 entry: 115 ; CHECK: invoke fastcc i32 @g.fastcc() #[[FOO_BAR_ATTR_IDX:[0-9]+]] [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ] 116 %x = call i32 @callee_5() [ "deopt"(i32 7) ] 117 ret i32 %x 118 } 119 120 define i32 @callee_6() alwaysinline personality i8 3 { 121 entry: 122 %v = call fastcc i32 @g.fastcc() #0 [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] 123 ret i32 %v 124 } 125 126 define i32 @caller_6() { 127 ; CHECK-LABEL: @caller_6( 128 entry: 129 ; CHECK: call fastcc i32 @g.fastcc() #[[FOO_BAR_ATTR_IDX]] [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ] 130 %x = call i32 @callee_6() [ "deopt"(i32 7) ] 131 ret i32 %x 132 } 133 134 define i32 @callee_7(i1 %val) alwaysinline personality i8 3 { 135 ; We want something that PruningFunctionCloner is not smart enough to 136 ; recognize, but can be recognized by recursivelySimplifyInstruction. 137 138 entry: 139 br i1 %val, label %check, label %precheck 140 141 precheck: 142 br label %check 143 144 check: 145 %p = phi i1 [ %val, %entry ], [ true, %precheck ] 146 br i1 %p, label %do.not, label %do 147 148 do.not: 149 ret i32 0 150 151 do: 152 %v = call fastcc i32 @g.fastcc() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] 153 ret i32 %v 154 } 155 156 define i32 @caller_7() { 157 ; CHECK-LABEL: @caller_7( 158 entry: 159 ; CHECK-NOT: call fastcc i32 @g.fastcc() 160 ; CHECK: ret i32 0 161 %x = call i32 @callee_7(i1 true) [ "deopt"(i32 7) ] 162 ret i32 %x 163 } 164 165 define i32 @callee_8(i1 %val) alwaysinline personality i8 3 { 166 ; We want something that PruningFunctionCloner is not smart enough to 167 ; recognize, but can be recognized by recursivelySimplifyInstruction. 168 169 entry: 170 br i1 %val, label %check, label %precheck 171 172 precheck: 173 br label %check 174 175 check: 176 %p = phi i1 [ %val, %entry ], [ true, %precheck ] 177 br i1 %p, label %do.not, label %do 178 179 do.not: 180 ret i32 0 181 182 do: 183 %phi = phi i32 [ 0, %check ], [ %v, %do ] 184 %v = call fastcc i32 @g.fastcc() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] 185 %ic = icmp eq i32 %v, 42 186 br i1 %ic, label %do, label %done 187 188 done: 189 ret i32 %phi 190 } 191 192 define i32 @caller_8() { 193 ; CHECK-LABEL: @caller_8( 194 entry: 195 ; CHECK-NOT: call fastcc i32 @g.fastcc() 196 ; CHECK: ret i32 0 197 %x = call i32 @callee_8(i1 true) [ "deopt"(i32 7) ] 198 ret i32 %x 199 } 200 201 attributes #0 = { "foo"="bar" } 202 203 ; CHECK: attributes #[[FOO_BAR_ATTR_IDX]] = { "foo"="bar" } 204