1; RUN: opt < %s -inline -S | FileCheck %s 2target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" 3 4define i32 @noattr_callee(i32 %i) { 5 ret i32 %i 6} 7 8define i32 @sanitize_address_callee(i32 %i) sanitize_address { 9 ret i32 %i 10} 11 12define i32 @sanitize_thread_callee(i32 %i) sanitize_thread { 13 ret i32 %i 14} 15 16define i32 @sanitize_memory_callee(i32 %i) sanitize_memory { 17 ret i32 %i 18} 19 20define i32 @safestack_callee(i32 %i) safestack { 21 ret i32 %i 22} 23 24define i32 @alwaysinline_callee(i32 %i) alwaysinline { 25 ret i32 %i 26} 27 28define i32 @alwaysinline_sanitize_address_callee(i32 %i) alwaysinline sanitize_address { 29 ret i32 %i 30} 31 32define i32 @alwaysinline_sanitize_thread_callee(i32 %i) alwaysinline sanitize_thread { 33 ret i32 %i 34} 35 36define i32 @alwaysinline_sanitize_memory_callee(i32 %i) alwaysinline sanitize_memory { 37 ret i32 %i 38} 39 40define i32 @alwaysinline_safestack_callee(i32 %i) alwaysinline safestack { 41 ret i32 %i 42} 43 44 45; Check that: 46; * noattr callee is inlined into noattr caller, 47; * sanitize_(address|memory|thread) callee is not inlined into noattr caller, 48; * alwaysinline callee is always inlined no matter what sanitize_* attributes are present. 49 50define i32 @test_no_sanitize_address(i32 %arg) { 51 %x1 = call i32 @noattr_callee(i32 %arg) 52 %x2 = call i32 @sanitize_address_callee(i32 %x1) 53 %x3 = call i32 @alwaysinline_callee(i32 %x2) 54 %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3) 55 ret i32 %x4 56; CHECK-LABEL: @test_no_sanitize_address( 57; CHECK-NEXT: @sanitize_address_callee 58; CHECK-NEXT: ret i32 59} 60 61define i32 @test_no_sanitize_memory(i32 %arg) { 62 %x1 = call i32 @noattr_callee(i32 %arg) 63 %x2 = call i32 @sanitize_memory_callee(i32 %x1) 64 %x3 = call i32 @alwaysinline_callee(i32 %x2) 65 %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3) 66 ret i32 %x4 67; CHECK-LABEL: @test_no_sanitize_memory( 68; CHECK-NEXT: @sanitize_memory_callee 69; CHECK-NEXT: ret i32 70} 71 72define i32 @test_no_sanitize_thread(i32 %arg) { 73 %x1 = call i32 @noattr_callee(i32 %arg) 74 %x2 = call i32 @sanitize_thread_callee(i32 %x1) 75 %x3 = call i32 @alwaysinline_callee(i32 %x2) 76 %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3) 77 ret i32 %x4 78; CHECK-LABEL: @test_no_sanitize_thread( 79; CHECK-NEXT: @sanitize_thread_callee 80; CHECK-NEXT: ret i32 81} 82 83 84; Check that: 85; * noattr callee is not inlined into sanitize_(address|memory|thread) caller, 86; * sanitize_(address|memory|thread) callee is inlined into the caller with the same attribute, 87; * alwaysinline callee is always inlined no matter what sanitize_* attributes are present. 88 89define i32 @test_sanitize_address(i32 %arg) sanitize_address { 90 %x1 = call i32 @noattr_callee(i32 %arg) 91 %x2 = call i32 @sanitize_address_callee(i32 %x1) 92 %x3 = call i32 @alwaysinline_callee(i32 %x2) 93 %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3) 94 ret i32 %x4 95; CHECK-LABEL: @test_sanitize_address( 96; CHECK-NEXT: @noattr_callee 97; CHECK-NEXT: ret i32 98} 99 100define i32 @test_sanitize_memory(i32 %arg) sanitize_memory { 101 %x1 = call i32 @noattr_callee(i32 %arg) 102 %x2 = call i32 @sanitize_memory_callee(i32 %x1) 103 %x3 = call i32 @alwaysinline_callee(i32 %x2) 104 %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3) 105 ret i32 %x4 106; CHECK-LABEL: @test_sanitize_memory( 107; CHECK-NEXT: @noattr_callee 108; CHECK-NEXT: ret i32 109} 110 111define i32 @test_sanitize_thread(i32 %arg) sanitize_thread { 112 %x1 = call i32 @noattr_callee(i32 %arg) 113 %x2 = call i32 @sanitize_thread_callee(i32 %x1) 114 %x3 = call i32 @alwaysinline_callee(i32 %x2) 115 %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3) 116 ret i32 %x4 117; CHECK-LABEL: @test_sanitize_thread( 118; CHECK-NEXT: @noattr_callee 119; CHECK-NEXT: ret i32 120} 121 122define i32 @test_safestack(i32 %arg) safestack { 123 %x1 = call i32 @noattr_callee(i32 %arg) 124 %x2 = call i32 @safestack_callee(i32 %x1) 125 %x3 = call i32 @alwaysinline_callee(i32 %x2) 126 %x4 = call i32 @alwaysinline_safestack_callee(i32 %x3) 127 ret i32 %x4 128; CHECK-LABEL: @test_safestack( 129; CHECK-NEXT: @noattr_callee 130; CHECK-NEXT: ret i32 131} 132 133; Check that a function doesn't get inlined if target-cpu strings don't match 134; exactly. 135define i32 @test_target_cpu_callee0(i32 %i) "target-cpu"="corei7" { 136 ret i32 %i 137} 138 139define i32 @test_target_cpu0(i32 %i) "target-cpu"="corei7" { 140 %1 = call i32 @test_target_cpu_callee0(i32 %i) 141 ret i32 %1 142; CHECK-LABEL: @test_target_cpu0( 143; CHECK-NOT: @test_target_cpu_callee0 144} 145 146define i32 @test_target_cpu_callee1(i32 %i) "target-cpu"="x86-64" { 147 ret i32 %i 148} 149 150define i32 @test_target_cpu1(i32 %i) "target-cpu"="corei7" { 151 %1 = call i32 @test_target_cpu_callee1(i32 %i) 152 ret i32 %1 153; CHECK-LABEL: @test_target_cpu1( 154; CHECK-NEXT: @test_target_cpu_callee1 155; CHECK-NEXT: ret i32 156} 157 158; Check that a function doesn't get inlined if target-features strings don't 159; match exactly. 160define i32 @test_target_features_callee0(i32 %i) "target-features"="+sse4.2" { 161 ret i32 %i 162} 163 164define i32 @test_target_features0(i32 %i) "target-features"="+sse4.2" { 165 %1 = call i32 @test_target_features_callee0(i32 %i) 166 ret i32 %1 167; CHECK-LABEL: @test_target_features0( 168; CHECK-NOT: @test_target_features_callee0 169} 170 171define i32 @test_target_features_callee1(i32 %i) "target-features"="+avx2" { 172 ret i32 %i 173} 174 175define i32 @test_target_features1(i32 %i) "target-features"="+sse4.2" { 176 %1 = call i32 @test_target_features_callee1(i32 %i) 177 ret i32 %1 178; CHECK-LABEL: @test_target_features1( 179; CHECK-NEXT: @test_target_features_callee1 180; CHECK-NEXT: ret i32 181} 182 183define i32 @less-precise-fpmad_callee0(i32 %i) "less-precise-fpmad"="false" { 184 ret i32 %i 185; CHECK: @less-precise-fpmad_callee0(i32 %i) [[FPMAD_FALSE:#[0-9]+]] { 186; CHECK-NEXT: ret i32 187} 188 189define i32 @less-precise-fpmad_callee1(i32 %i) "less-precise-fpmad"="true" { 190 ret i32 %i 191; CHECK: @less-precise-fpmad_callee1(i32 %i) [[FPMAD_TRUE:#[0-9]+]] { 192; CHECK-NEXT: ret i32 193} 194 195define i32 @test_less-precise-fpmad0(i32 %i) "less-precise-fpmad"="false" { 196 %1 = call i32 @less-precise-fpmad_callee0(i32 %i) 197 ret i32 %1 198; CHECK: @test_less-precise-fpmad0(i32 %i) [[FPMAD_FALSE]] { 199; CHECK-NEXT: ret i32 200} 201 202define i32 @test_less-precise-fpmad1(i32 %i) "less-precise-fpmad"="false" { 203 %1 = call i32 @less-precise-fpmad_callee1(i32 %i) 204 ret i32 %1 205; CHECK: @test_less-precise-fpmad1(i32 %i) [[FPMAD_FALSE]] { 206; CHECK-NEXT: ret i32 207} 208 209define i32 @test_less-precise-fpmad2(i32 %i) "less-precise-fpmad"="true" { 210 %1 = call i32 @less-precise-fpmad_callee0(i32 %i) 211 ret i32 %1 212; CHECK: @test_less-precise-fpmad2(i32 %i) [[FPMAD_FALSE]] { 213; CHECK-NEXT: ret i32 214} 215 216define i32 @test_less-precise-fpmad3(i32 %i) "less-precise-fpmad"="true" { 217 %1 = call i32 @less-precise-fpmad_callee1(i32 %i) 218 ret i32 %1 219; CHECK: @test_less-precise-fpmad3(i32 %i) [[FPMAD_TRUE]] { 220; CHECK-NEXT: ret i32 221} 222 223define i32 @no-implicit-float_callee0(i32 %i) { 224 ret i32 %i 225; CHECK: @no-implicit-float_callee0(i32 %i) { 226; CHECK-NEXT: ret i32 227} 228 229define i32 @no-implicit-float_callee1(i32 %i) noimplicitfloat { 230 ret i32 %i 231; CHECK: @no-implicit-float_callee1(i32 %i) [[NOIMPLICITFLOAT:#[0-9]+]] { 232; CHECK-NEXT: ret i32 233} 234 235define i32 @test_no-implicit-float0(i32 %i) { 236 %1 = call i32 @no-implicit-float_callee0(i32 %i) 237 ret i32 %1 238; CHECK: @test_no-implicit-float0(i32 %i) { 239; CHECK-NEXT: ret i32 240} 241 242define i32 @test_no-implicit-float1(i32 %i) { 243 %1 = call i32 @no-implicit-float_callee1(i32 %i) 244 ret i32 %1 245; CHECK: @test_no-implicit-float1(i32 %i) [[NOIMPLICITFLOAT]] { 246; CHECK-NEXT: ret i32 247} 248 249define i32 @test_no-implicit-float2(i32 %i) noimplicitfloat { 250 %1 = call i32 @no-implicit-float_callee0(i32 %i) 251 ret i32 %1 252; CHECK: @test_no-implicit-float2(i32 %i) [[NOIMPLICITFLOAT]] { 253; CHECK-NEXT: ret i32 254} 255 256define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat { 257 %1 = call i32 @no-implicit-float_callee1(i32 %i) 258 ret i32 %1 259; CHECK: @test_no-implicit-float3(i32 %i) [[NOIMPLICITFLOAT]] { 260; CHECK-NEXT: ret i32 261} 262 263; Check that no-jump-tables flag propagates from inlined callee to caller 264 265define i32 @no-use-jump-tables_callee0(i32 %i) { 266 ret i32 %i 267; CHECK: @no-use-jump-tables_callee0(i32 %i) { 268; CHECK-NEXT: ret i32 269} 270 271define i32 @no-use-jump-tables_callee1(i32 %i) "no-jump-tables"="true" { 272 ret i32 %i 273; CHECK: @no-use-jump-tables_callee1(i32 %i) [[NOUSEJUMPTABLES:#[0-9]+]] { 274; CHECK-NEXT: ret i32 275} 276 277define i32 @test_no-use-jump-tables0(i32 %i) { 278 %1 = call i32 @no-use-jump-tables_callee0(i32 %i) 279 ret i32 %1 280; CHECK: @test_no-use-jump-tables0(i32 %i) { 281; CHECK-NEXT: ret i32 282} 283 284define i32 @test_no-use-jump-tables1(i32 %i) { 285 %1 = call i32 @no-use-jump-tables_callee1(i32 %i) 286 ret i32 %1 287; CHECK: @test_no-use-jump-tables1(i32 %i) [[NOUSEJUMPTABLES]] { 288; CHECK-NEXT: ret i32 289} 290 291define i32 @test_no-use-jump-tables2(i32 %i) "no-jump-tables"="true" { 292 %1 = call i32 @no-use-jump-tables_callee0(i32 %i) 293 ret i32 %1 294; CHECK: @test_no-use-jump-tables2(i32 %i) [[NOUSEJUMPTABLES]] { 295; CHECK-NEXT: ret i32 296} 297 298define i32 @test_no-use-jump-tables3(i32 %i) "no-jump-tables"="true" { 299 %1 = call i32 @no-use-jump-tables_callee1(i32 %i) 300 ret i32 %1 301; CHECK: @test_no-use-jump-tables3(i32 %i) [[NOUSEJUMPTABLES]] { 302; CHECK-NEXT: ret i32 303} 304 305; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" } 306; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" } 307; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat } 308; CHECK: attributes [[NOUSEJUMPTABLES]] = { "no-jump-tables"="true" }