1 ; RUN: opt < %s -inline -S | FileCheck %s 2 ; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s 3 target 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" 4 5 define i32 @noattr_callee(i32 %i) { 6 ret i32 %i 7 } 8 9 define i32 @sanitize_address_callee(i32 %i) sanitize_address { 10 ret i32 %i 11 } 12 13 define i32 @sanitize_hwaddress_callee(i32 %i) sanitize_hwaddress { 14 ret i32 %i 15 } 16 17 define i32 @sanitize_thread_callee(i32 %i) sanitize_thread { 18 ret i32 %i 19 } 20 21 define i32 @sanitize_memory_callee(i32 %i) sanitize_memory { 22 ret i32 %i 23 } 24 25 define i32 @safestack_callee(i32 %i) safestack { 26 ret i32 %i 27 } 28 29 define i32 @alwaysinline_callee(i32 %i) alwaysinline { 30 ret i32 %i 31 } 32 33 define i32 @alwaysinline_sanitize_address_callee(i32 %i) alwaysinline sanitize_address { 34 ret i32 %i 35 } 36 37 define i32 @alwaysinline_sanitize_hwaddress_callee(i32 %i) alwaysinline sanitize_hwaddress { 38 ret i32 %i 39 } 40 41 define i32 @alwaysinline_sanitize_thread_callee(i32 %i) alwaysinline sanitize_thread { 42 ret i32 %i 43 } 44 45 define i32 @alwaysinline_sanitize_memory_callee(i32 %i) alwaysinline sanitize_memory { 46 ret i32 %i 47 } 48 49 define i32 @alwaysinline_safestack_callee(i32 %i) alwaysinline safestack { 50 ret i32 %i 51 } 52 53 54 ; Check that: 55 ; * noattr callee is inlined into noattr caller, 56 ; * sanitize_(address|memory|thread) callee is not inlined into noattr caller, 57 ; * alwaysinline callee is always inlined no matter what sanitize_* attributes are present. 58 59 define i32 @test_no_sanitize_address(i32 %arg) { 60 %x1 = call i32 @noattr_callee(i32 %arg) 61 %x2 = call i32 @sanitize_address_callee(i32 %x1) 62 %x3 = call i32 @alwaysinline_callee(i32 %x2) 63 %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3) 64 ret i32 %x4 65 ; CHECK-LABEL: @test_no_sanitize_address( 66 ; CHECK-NEXT: @sanitize_address_callee 67 ; CHECK-NEXT: ret i32 68 } 69 70 define i32 @test_no_sanitize_hwaddress(i32 %arg) { 71 %x1 = call i32 @noattr_callee(i32 %arg) 72 %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1) 73 %x3 = call i32 @alwaysinline_callee(i32 %x2) 74 %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3) 75 ret i32 %x4 76 ; CHECK-LABEL: @test_no_sanitize_hwaddress( 77 ; CHECK-NEXT: @sanitize_hwaddress_callee 78 ; CHECK-NEXT: ret i32 79 } 80 81 define i32 @test_no_sanitize_memory(i32 %arg) { 82 %x1 = call i32 @noattr_callee(i32 %arg) 83 %x2 = call i32 @sanitize_memory_callee(i32 %x1) 84 %x3 = call i32 @alwaysinline_callee(i32 %x2) 85 %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3) 86 ret i32 %x4 87 ; CHECK-LABEL: @test_no_sanitize_memory( 88 ; CHECK-NEXT: @sanitize_memory_callee 89 ; CHECK-NEXT: ret i32 90 } 91 92 define i32 @test_no_sanitize_thread(i32 %arg) { 93 %x1 = call i32 @noattr_callee(i32 %arg) 94 %x2 = call i32 @sanitize_thread_callee(i32 %x1) 95 %x3 = call i32 @alwaysinline_callee(i32 %x2) 96 %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3) 97 ret i32 %x4 98 ; CHECK-LABEL: @test_no_sanitize_thread( 99 ; CHECK-NEXT: @sanitize_thread_callee 100 ; CHECK-NEXT: ret i32 101 } 102 103 104 ; Check that: 105 ; * noattr callee is not inlined into sanitize_(address|memory|thread) caller, 106 ; * sanitize_(address|memory|thread) callee is inlined into the caller with the same attribute, 107 ; * alwaysinline callee is always inlined no matter what sanitize_* attributes are present. 108 109 define i32 @test_sanitize_address(i32 %arg) sanitize_address { 110 %x1 = call i32 @noattr_callee(i32 %arg) 111 %x2 = call i32 @sanitize_address_callee(i32 %x1) 112 %x3 = call i32 @alwaysinline_callee(i32 %x2) 113 %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3) 114 ret i32 %x4 115 ; CHECK-LABEL: @test_sanitize_address( 116 ; CHECK-NEXT: @noattr_callee 117 ; CHECK-NEXT: ret i32 118 } 119 120 define i32 @test_sanitize_hwaddress(i32 %arg) sanitize_hwaddress { 121 %x1 = call i32 @noattr_callee(i32 %arg) 122 %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1) 123 %x3 = call i32 @alwaysinline_callee(i32 %x2) 124 %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3) 125 ret i32 %x4 126 ; CHECK-LABEL: @test_sanitize_hwaddress( 127 ; CHECK-NEXT: @noattr_callee 128 ; CHECK-NEXT: ret i32 129 } 130 131 define i32 @test_sanitize_memory(i32 %arg) sanitize_memory { 132 %x1 = call i32 @noattr_callee(i32 %arg) 133 %x2 = call i32 @sanitize_memory_callee(i32 %x1) 134 %x3 = call i32 @alwaysinline_callee(i32 %x2) 135 %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3) 136 ret i32 %x4 137 ; CHECK-LABEL: @test_sanitize_memory( 138 ; CHECK-NEXT: @noattr_callee 139 ; CHECK-NEXT: ret i32 140 } 141 142 define i32 @test_sanitize_thread(i32 %arg) sanitize_thread { 143 %x1 = call i32 @noattr_callee(i32 %arg) 144 %x2 = call i32 @sanitize_thread_callee(i32 %x1) 145 %x3 = call i32 @alwaysinline_callee(i32 %x2) 146 %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3) 147 ret i32 %x4 148 ; CHECK-LABEL: @test_sanitize_thread( 149 ; CHECK-NEXT: @noattr_callee 150 ; CHECK-NEXT: ret i32 151 } 152 153 define i32 @test_safestack(i32 %arg) safestack { 154 %x1 = call i32 @noattr_callee(i32 %arg) 155 %x2 = call i32 @safestack_callee(i32 %x1) 156 %x3 = call i32 @alwaysinline_callee(i32 %x2) 157 %x4 = call i32 @alwaysinline_safestack_callee(i32 %x3) 158 ret i32 %x4 159 ; CHECK-LABEL: @test_safestack( 160 ; CHECK-NEXT: @noattr_callee 161 ; CHECK-NEXT: ret i32 162 } 163 164 ; Check that a function doesn't get inlined if target-cpu strings don't match 165 ; exactly. 166 define i32 @test_target_cpu_callee0(i32 %i) "target-cpu"="corei7" { 167 ret i32 %i 168 } 169 170 define i32 @test_target_cpu0(i32 %i) "target-cpu"="corei7" { 171 %1 = call i32 @test_target_cpu_callee0(i32 %i) 172 ret i32 %1 173 ; CHECK-LABEL: @test_target_cpu0( 174 ; CHECK-NOT: @test_target_cpu_callee0 175 } 176 177 define i32 @test_target_cpu_callee1(i32 %i) "target-cpu"="x86-64" { 178 ret i32 %i 179 } 180 181 define i32 @test_target_cpu1(i32 %i) "target-cpu"="corei7" { 182 %1 = call i32 @test_target_cpu_callee1(i32 %i) 183 ret i32 %1 184 ; CHECK-LABEL: @test_target_cpu1( 185 ; CHECK-NEXT: @test_target_cpu_callee1 186 ; CHECK-NEXT: ret i32 187 } 188 189 ; Check that a function doesn't get inlined if target-features strings don't 190 ; match exactly. 191 define i32 @test_target_features_callee0(i32 %i) "target-features"="+sse4.2" { 192 ret i32 %i 193 } 194 195 define i32 @test_target_features0(i32 %i) "target-features"="+sse4.2" { 196 %1 = call i32 @test_target_features_callee0(i32 %i) 197 ret i32 %1 198 ; CHECK-LABEL: @test_target_features0( 199 ; CHECK-NOT: @test_target_features_callee0 200 } 201 202 define i32 @test_target_features_callee1(i32 %i) "target-features"="+avx2" { 203 ret i32 %i 204 } 205 206 define i32 @test_target_features1(i32 %i) "target-features"="+sse4.2" { 207 %1 = call i32 @test_target_features_callee1(i32 %i) 208 ret i32 %1 209 ; CHECK-LABEL: @test_target_features1( 210 ; CHECK-NEXT: @test_target_features_callee1 211 ; CHECK-NEXT: ret i32 212 } 213 214 define i32 @less-precise-fpmad_callee0(i32 %i) "less-precise-fpmad"="false" { 215 ret i32 %i 216 ; CHECK: @less-precise-fpmad_callee0(i32 %i) [[FPMAD_FALSE:#[0-9]+]] { 217 ; CHECK-NEXT: ret i32 218 } 219 220 define i32 @less-precise-fpmad_callee1(i32 %i) "less-precise-fpmad"="true" { 221 ret i32 %i 222 ; CHECK: @less-precise-fpmad_callee1(i32 %i) [[FPMAD_TRUE:#[0-9]+]] { 223 ; CHECK-NEXT: ret i32 224 } 225 226 define i32 @test_less-precise-fpmad0(i32 %i) "less-precise-fpmad"="false" { 227 %1 = call i32 @less-precise-fpmad_callee0(i32 %i) 228 ret i32 %1 229 ; CHECK: @test_less-precise-fpmad0(i32 %i) [[FPMAD_FALSE]] { 230 ; CHECK-NEXT: ret i32 231 } 232 233 define i32 @test_less-precise-fpmad1(i32 %i) "less-precise-fpmad"="false" { 234 %1 = call i32 @less-precise-fpmad_callee1(i32 %i) 235 ret i32 %1 236 ; CHECK: @test_less-precise-fpmad1(i32 %i) [[FPMAD_FALSE]] { 237 ; CHECK-NEXT: ret i32 238 } 239 240 define i32 @test_less-precise-fpmad2(i32 %i) "less-precise-fpmad"="true" { 241 %1 = call i32 @less-precise-fpmad_callee0(i32 %i) 242 ret i32 %1 243 ; CHECK: @test_less-precise-fpmad2(i32 %i) [[FPMAD_FALSE]] { 244 ; CHECK-NEXT: ret i32 245 } 246 247 define i32 @test_less-precise-fpmad3(i32 %i) "less-precise-fpmad"="true" { 248 %1 = call i32 @less-precise-fpmad_callee1(i32 %i) 249 ret i32 %1 250 ; CHECK: @test_less-precise-fpmad3(i32 %i) [[FPMAD_TRUE]] { 251 ; CHECK-NEXT: ret i32 252 } 253 254 define i32 @no-implicit-float_callee0(i32 %i) { 255 ret i32 %i 256 ; CHECK: @no-implicit-float_callee0(i32 %i) { 257 ; CHECK-NEXT: ret i32 258 } 259 260 define i32 @no-implicit-float_callee1(i32 %i) noimplicitfloat { 261 ret i32 %i 262 ; CHECK: @no-implicit-float_callee1(i32 %i) [[NOIMPLICITFLOAT:#[0-9]+]] { 263 ; CHECK-NEXT: ret i32 264 } 265 266 define i32 @test_no-implicit-float0(i32 %i) { 267 %1 = call i32 @no-implicit-float_callee0(i32 %i) 268 ret i32 %1 269 ; CHECK: @test_no-implicit-float0(i32 %i) { 270 ; CHECK-NEXT: ret i32 271 } 272 273 define i32 @test_no-implicit-float1(i32 %i) { 274 %1 = call i32 @no-implicit-float_callee1(i32 %i) 275 ret i32 %1 276 ; CHECK: @test_no-implicit-float1(i32 %i) [[NOIMPLICITFLOAT]] { 277 ; CHECK-NEXT: ret i32 278 } 279 280 define i32 @test_no-implicit-float2(i32 %i) noimplicitfloat { 281 %1 = call i32 @no-implicit-float_callee0(i32 %i) 282 ret i32 %1 283 ; CHECK: @test_no-implicit-float2(i32 %i) [[NOIMPLICITFLOAT]] { 284 ; CHECK-NEXT: ret i32 285 } 286 287 define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat { 288 %1 = call i32 @no-implicit-float_callee1(i32 %i) 289 ret i32 %1 290 ; CHECK: @test_no-implicit-float3(i32 %i) [[NOIMPLICITFLOAT]] { 291 ; CHECK-NEXT: ret i32 292 } 293 294 ; Check that no-jump-tables flag propagates from inlined callee to caller 295 296 define i32 @no-use-jump-tables_callee0(i32 %i) { 297 ret i32 %i 298 ; CHECK: @no-use-jump-tables_callee0(i32 %i) { 299 ; CHECK-NEXT: ret i32 300 } 301 302 define i32 @no-use-jump-tables_callee1(i32 %i) "no-jump-tables"="true" { 303 ret i32 %i 304 ; CHECK: @no-use-jump-tables_callee1(i32 %i) [[NOUSEJUMPTABLES:#[0-9]+]] { 305 ; CHECK-NEXT: ret i32 306 } 307 308 define i32 @test_no-use-jump-tables0(i32 %i) { 309 %1 = call i32 @no-use-jump-tables_callee0(i32 %i) 310 ret i32 %1 311 ; CHECK: @test_no-use-jump-tables0(i32 %i) { 312 ; CHECK-NEXT: ret i32 313 } 314 315 define i32 @test_no-use-jump-tables1(i32 %i) { 316 %1 = call i32 @no-use-jump-tables_callee1(i32 %i) 317 ret i32 %1 318 ; CHECK: @test_no-use-jump-tables1(i32 %i) [[NOUSEJUMPTABLES]] { 319 ; CHECK-NEXT: ret i32 320 } 321 322 define i32 @test_no-use-jump-tables2(i32 %i) "no-jump-tables"="true" { 323 %1 = call i32 @no-use-jump-tables_callee0(i32 %i) 324 ret i32 %1 325 ; CHECK: @test_no-use-jump-tables2(i32 %i) [[NOUSEJUMPTABLES]] { 326 ; CHECK-NEXT: ret i32 327 } 328 329 define i32 @test_no-use-jump-tables3(i32 %i) "no-jump-tables"="true" { 330 %1 = call i32 @no-use-jump-tables_callee1(i32 %i) 331 ret i32 %1 332 ; CHECK: @test_no-use-jump-tables3(i32 %i) [[NOUSEJUMPTABLES]] { 333 ; CHECK-NEXT: ret i32 334 } 335 336 ; Callee with "null-pointer-is-valid"="true" attribute should not be inlined 337 ; into a caller without this attribute. 338 ; Exception: alwaysinline callee can still be inlined but 339 ; "null-pointer-is-valid"="true" should get copied to caller. 340 341 define i32 @null-pointer-is-valid_callee0(i32 %i) "null-pointer-is-valid"="true" { 342 ret i32 %i 343 ; CHECK: @null-pointer-is-valid_callee0(i32 %i) 344 ; CHECK-NEXT: ret i32 345 } 346 347 define i32 @null-pointer-is-valid_callee1(i32 %i) alwaysinline "null-pointer-is-valid"="true" { 348 ret i32 %i 349 ; CHECK: @null-pointer-is-valid_callee1(i32 %i) 350 ; CHECK-NEXT: ret i32 351 } 352 353 define i32 @null-pointer-is-valid_callee2(i32 %i) { 354 ret i32 %i 355 ; CHECK: @null-pointer-is-valid_callee2(i32 %i) 356 ; CHECK-NEXT: ret i32 357 } 358 359 ; No inlining since caller does not have "null-pointer-is-valid"="true" attribute. 360 define i32 @test_null-pointer-is-valid0(i32 %i) { 361 %1 = call i32 @null-pointer-is-valid_callee0(i32 %i) 362 ret i32 %1 363 ; CHECK: @test_null-pointer-is-valid0( 364 ; CHECK: call i32 @null-pointer-is-valid_callee0 365 ; CHECK-NEXT: ret i32 366 } 367 368 ; alwaysinline should force inlining even when caller does not have 369 ; "null-pointer-is-valid"="true" attribute. However, the attribute should be 370 ; copied to caller. 371 define i32 @test_null-pointer-is-valid1(i32 %i) "null-pointer-is-valid"="false" { 372 %1 = call i32 @null-pointer-is-valid_callee1(i32 %i) 373 ret i32 %1 374 ; CHECK: @test_null-pointer-is-valid1(i32 %i) [[NULLPOINTERISVALID:#[0-9]+]] { 375 ; CHECK-NEXT: ret i32 376 } 377 378 ; Can inline since both caller and callee have "null-pointer-is-valid"="true" 379 ; attribute. 380 define i32 @test_null-pointer-is-valid2(i32 %i) "null-pointer-is-valid"="true" { 381 %1 = call i32 @null-pointer-is-valid_callee2(i32 %i) 382 ret i32 %1 383 ; CHECK: @test_null-pointer-is-valid2(i32 %i) [[NULLPOINTERISVALID]] { 384 ; CHECK-NEXT: ret i32 385 } 386 387 ; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" } 388 ; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" } 389 ; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat } 390 ; CHECK: attributes [[NOUSEJUMPTABLES]] = { "no-jump-tables"="true" } 391 ; CHECK: attributes [[NULLPOINTERISVALID]] = { "null-pointer-is-valid"="true" } 392