1; RUN: opt -S -always-inline < %s | FileCheck %s 2 3declare void @f() 4declare i32 @g() 5declare fastcc i32 @g.fastcc() 6 7define i32 @callee_0() alwaysinline { 8 entry: 9 call void @f() 10 ret i32 2 11} 12 13define 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 23define 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 31define 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 44define 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 50define 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 60define 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 66define 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 80define 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 92define 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 100define 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 112define 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 120define 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 126define 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 134define 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 156define 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 165define 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 192define 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 201attributes #0 = { "foo"="bar" } 202 203; CHECK: attributes #[[FOO_BAR_ATTR_IDX]] = { "foo"="bar" } 204