657 lines · plain
1; RUN: opt < %s -passes=inline -S | FileCheck %s2; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s3target 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 5define i32 @noattr_callee(i32 %i) {6 ret i32 %i7}8 9define i32 @sanitize_address_callee(i32 %i) sanitize_address {10 ret i32 %i11}12 13define i32 @sanitize_hwaddress_callee(i32 %i) sanitize_hwaddress {14 ret i32 %i15}16 17define i32 @sanitize_thread_callee(i32 %i) sanitize_thread {18 ret i32 %i19}20 21define i32 @sanitize_memory_callee(i32 %i) sanitize_memory {22 ret i32 %i23}24 25define i32 @sanitize_memtag_callee(i32 %i) sanitize_memtag {26 ret i32 %i27}28 29define i32 @sanitize_alloc_token_callee(i32 %i) sanitize_alloc_token {30 ret i32 %i31}32 33define i32 @safestack_callee(i32 %i) safestack {34 ret i32 %i35}36 37define i32 @slh_callee(i32 %i) speculative_load_hardening {38 ret i32 %i39}40 41define i32 @alwaysinline_callee(i32 %i) alwaysinline {42 ret i32 %i43}44 45define i32 @alwaysinline_sanitize_address_callee(i32 %i) alwaysinline sanitize_address {46 ret i32 %i47}48 49define i32 @alwaysinline_sanitize_hwaddress_callee(i32 %i) alwaysinline sanitize_hwaddress {50 ret i32 %i51}52 53define i32 @alwaysinline_sanitize_thread_callee(i32 %i) alwaysinline sanitize_thread {54 ret i32 %i55}56 57define i32 @alwaysinline_sanitize_memory_callee(i32 %i) alwaysinline sanitize_memory {58 ret i32 %i59}60 61define i32 @alwaysinline_sanitize_memtag_callee(i32 %i) alwaysinline sanitize_memtag {62 ret i32 %i63}64 65define i32 @alwaysinline_sanitize_alloc_token_callee(i32 %i) alwaysinline sanitize_alloc_token {66 ret i32 %i67}68 69define i32 @alwaysinline_safestack_callee(i32 %i) alwaysinline safestack {70 ret i32 %i71}72 73 74; Check that:75; * noattr callee is inlined into noattr caller,76; * sanitize_(address|memory|thread) callee is not inlined into noattr caller,77; * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.78 79define i32 @test_no_sanitize_address(i32 %arg) {80 %x1 = call i32 @noattr_callee(i32 %arg)81 %x2 = call i32 @sanitize_address_callee(i32 %x1)82 %x3 = call i32 @alwaysinline_callee(i32 %x2)83 %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)84 ret i32 %x485; CHECK-LABEL: @test_no_sanitize_address(86; CHECK-NEXT: @sanitize_address_callee87; CHECK-NEXT: ret i3288}89 90define i32 @test_no_sanitize_hwaddress(i32 %arg) {91 %x1 = call i32 @noattr_callee(i32 %arg)92 %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)93 %x3 = call i32 @alwaysinline_callee(i32 %x2)94 %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)95 ret i32 %x496; CHECK-LABEL: @test_no_sanitize_hwaddress(97; CHECK-NEXT: @sanitize_hwaddress_callee98; CHECK-NEXT: ret i3299}100 101define i32 @test_no_sanitize_memory(i32 %arg) {102 %x1 = call i32 @noattr_callee(i32 %arg)103 %x2 = call i32 @sanitize_memory_callee(i32 %x1)104 %x3 = call i32 @alwaysinline_callee(i32 %x2)105 %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)106 ret i32 %x4107; CHECK-LABEL: @test_no_sanitize_memory(108; CHECK-NEXT: @sanitize_memory_callee109; CHECK-NEXT: ret i32110}111 112define i32 @test_no_sanitize_thread(i32 %arg) {113 %x1 = call i32 @noattr_callee(i32 %arg)114 %x2 = call i32 @sanitize_thread_callee(i32 %x1)115 %x3 = call i32 @alwaysinline_callee(i32 %x2)116 %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)117 ret i32 %x4118; CHECK-LABEL: @test_no_sanitize_thread(119; CHECK-NEXT: @sanitize_thread_callee120; CHECK-NEXT: ret i32121}122 123define i32 @test_no_sanitize_memtag(i32 %arg) {124 %x1 = call i32 @noattr_callee(i32 %arg)125 %x2 = call i32 @sanitize_memtag_callee(i32 %x1)126 %x3 = call i32 @alwaysinline_callee(i32 %x2)127 %x4 = call i32 @alwaysinline_sanitize_memtag_callee(i32 %x3)128 ret i32 %x4129; CHECK-LABEL: @test_no_sanitize_memtag(130; CHECK-NEXT: @sanitize_memtag_callee131; CHECK-NEXT: ret i32132}133 134 135; Check that:136; * noattr callee is not inlined into sanitize_(address|memory|thread) caller,137; * sanitize_(address|memory|thread) callee is inlined into the caller with the same attribute,138; * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.139 140define i32 @test_sanitize_address(i32 %arg) sanitize_address {141 %x1 = call i32 @noattr_callee(i32 %arg)142 %x2 = call i32 @sanitize_address_callee(i32 %x1)143 %x3 = call i32 @alwaysinline_callee(i32 %x2)144 %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)145 ret i32 %x4146; CHECK-LABEL: @test_sanitize_address(147; CHECK-NEXT: @noattr_callee148; CHECK-NEXT: ret i32149}150 151define i32 @test_sanitize_hwaddress(i32 %arg) sanitize_hwaddress {152 %x1 = call i32 @noattr_callee(i32 %arg)153 %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)154 %x3 = call i32 @alwaysinline_callee(i32 %x2)155 %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)156 ret i32 %x4157; CHECK-LABEL: @test_sanitize_hwaddress(158; CHECK-NEXT: @noattr_callee159; CHECK-NEXT: ret i32160}161 162define i32 @test_sanitize_memory(i32 %arg) sanitize_memory {163 %x1 = call i32 @noattr_callee(i32 %arg)164 %x2 = call i32 @sanitize_memory_callee(i32 %x1)165 %x3 = call i32 @alwaysinline_callee(i32 %x2)166 %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)167 ret i32 %x4168; CHECK-LABEL: @test_sanitize_memory(169; CHECK-NEXT: @noattr_callee170; CHECK-NEXT: ret i32171}172 173define i32 @test_sanitize_thread(i32 %arg) sanitize_thread {174 %x1 = call i32 @noattr_callee(i32 %arg)175 %x2 = call i32 @sanitize_thread_callee(i32 %x1)176 %x3 = call i32 @alwaysinline_callee(i32 %x2)177 %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)178 ret i32 %x4179; CHECK-LABEL: @test_sanitize_thread(180; CHECK-NEXT: @noattr_callee181; CHECK-NEXT: ret i32182}183 184define i32 @test_sanitize_memtag(i32 %arg) sanitize_memtag {185 %x1 = call i32 @noattr_callee(i32 %arg)186 %x2 = call i32 @sanitize_memtag_callee(i32 %x1)187 %x3 = call i32 @alwaysinline_callee(i32 %x2)188 %x4 = call i32 @alwaysinline_sanitize_memtag_callee(i32 %x3)189 ret i32 %x4190; CHECK-LABEL: @test_sanitize_memtag(191; CHECK-NEXT: @noattr_callee192; CHECK-NEXT: ret i32193}194 195; ---------------------------------------------------------------------------- ;196 197; Can inline sanitize_alloc_token functions into a noattr function. The198; attribute is *not* viral, otherwise may break code.199define i32 @test_no_sanitize_alloc_token(i32 %arg) {200; CHECK-LABEL: @test_no_sanitize_alloc_token(201; CHECK-SAME: ) {202; CHECK-NOT: call203; CHECK: ret i32204entry:205 %x1 = call i32 @noattr_callee(i32 %arg)206 %x2 = call i32 @sanitize_alloc_token_callee(i32 %x1)207 %x3 = call i32 @alwaysinline_callee(i32 %x2)208 %x4 = call i32 @alwaysinline_sanitize_alloc_token_callee(i32 %x3)209 ret i32 %x4210}211 212; Can inline noattr functions into a sanitize_alloc_token function. If213; inlinable noattr functions cannot be instrumented, they should be marked with214; explicit noinline.215define i32 @test_sanitize_alloc_token(i32 %arg) sanitize_alloc_token {216; CHECK-LABEL: @test_sanitize_alloc_token(217; CHECK-SAME: ) [[SANITIZE_ALLOC_TOKEN:.*]] {218; CHECK-NOT: call219; CHECK: ret i32220entry:221 %x1 = call i32 @noattr_callee(i32 %arg)222 %x2 = call i32 @sanitize_alloc_token_callee(i32 %x1)223 %x3 = call i32 @alwaysinline_callee(i32 %x2)224 %x4 = call i32 @alwaysinline_sanitize_alloc_token_callee(i32 %x3)225 ret i32 %x4226}227 228define i32 @test_safestack(i32 %arg) safestack {229 %x1 = call i32 @noattr_callee(i32 %arg)230 %x2 = call i32 @safestack_callee(i32 %x1)231 %x3 = call i32 @alwaysinline_callee(i32 %x2)232 %x4 = call i32 @alwaysinline_safestack_callee(i32 %x3)233 ret i32 %x4234; CHECK-LABEL: @test_safestack(235; CHECK-NEXT: @noattr_callee236; CHECK-NEXT: ret i32237}238 239; Can inline a normal function into an SLH'ed function.240define i32 @test_caller_slh(i32 %i) speculative_load_hardening {241; CHECK-LABEL: @test_caller_slh(242; CHECK-SAME: ) [[SLH:.*]] {243; CHECK-NOT: call244; CHECK: ret i32245entry:246 %callee = call i32 @noattr_callee(i32 %i)247 ret i32 %callee248}249 250; Can inline a SLH'ed function into a normal one, propagating SLH.251define i32 @test_callee_slh(i32 %i) {252; CHECK-LABEL: @test_callee_slh(253; CHECK-SAME: ) [[SLH:.*]] {254; CHECK-NOT: call255; CHECK: ret i32256entry:257 %callee = call i32 @slh_callee(i32 %i)258 ret i32 %callee259}260 261; Check that a function doesn't get inlined if target-cpu strings don't match262; exactly.263define i32 @test_target_cpu_callee0(i32 %i) "target-cpu"="corei7" {264 ret i32 %i265}266 267define i32 @test_target_cpu0(i32 %i) "target-cpu"="corei7" {268 %1 = call i32 @test_target_cpu_callee0(i32 %i)269 ret i32 %1270; CHECK-LABEL: @test_target_cpu0(271; CHECK-NOT: @test_target_cpu_callee0272}273 274define i32 @test_target_cpu_callee1(i32 %i) "target-cpu"="x86-64" {275 ret i32 %i276}277 278define i32 @test_target_cpu1(i32 %i) "target-cpu"="corei7" {279 %1 = call i32 @test_target_cpu_callee1(i32 %i)280 ret i32 %1281; CHECK-LABEL: @test_target_cpu1(282; CHECK-NEXT: @test_target_cpu_callee1283; CHECK-NEXT: ret i32284}285 286; Check that a function doesn't get inlined if target-features strings don't287; match exactly.288define i32 @test_target_features_callee0(i32 %i) "target-features"="+sse4.2" {289 ret i32 %i290}291 292define i32 @test_target_features0(i32 %i) "target-features"="+sse4.2" {293 %1 = call i32 @test_target_features_callee0(i32 %i)294 ret i32 %1295; CHECK-LABEL: @test_target_features0(296; CHECK-NOT: @test_target_features_callee0297}298 299define i32 @test_target_features_callee1(i32 %i) "target-features"="+avx2" {300 ret i32 %i301}302 303define i32 @test_target_features1(i32 %i) "target-features"="+sse4.2" {304 %1 = call i32 @test_target_features_callee1(i32 %i)305 ret i32 %1306; CHECK-LABEL: @test_target_features1(307; CHECK-NEXT: @test_target_features_callee1308; CHECK-NEXT: ret i32309}310 311define i32 @less-precise-fpmad_callee0(i32 %i) "less-precise-fpmad"="false" {312 ret i32 %i313; CHECK: @less-precise-fpmad_callee0(i32 %i) [[FPMAD_FALSE:#[0-9]+]] {314; CHECK-NEXT: ret i32315}316 317define i32 @less-precise-fpmad_callee1(i32 %i) "less-precise-fpmad"="true" {318 ret i32 %i319; CHECK: @less-precise-fpmad_callee1(i32 %i) [[FPMAD_TRUE:#[0-9]+]] {320; CHECK-NEXT: ret i32321}322 323define i32 @test_less-precise-fpmad0(i32 %i) "less-precise-fpmad"="false" {324 %1 = call i32 @less-precise-fpmad_callee0(i32 %i)325 ret i32 %1326; CHECK: @test_less-precise-fpmad0(i32 %i) [[FPMAD_FALSE]] {327; CHECK-NEXT: ret i32328}329 330define i32 @test_less-precise-fpmad1(i32 %i) "less-precise-fpmad"="false" {331 %1 = call i32 @less-precise-fpmad_callee1(i32 %i)332 ret i32 %1333; CHECK: @test_less-precise-fpmad1(i32 %i) [[FPMAD_FALSE]] {334; CHECK-NEXT: ret i32335}336 337define i32 @test_less-precise-fpmad2(i32 %i) "less-precise-fpmad"="true" {338 %1 = call i32 @less-precise-fpmad_callee0(i32 %i)339 ret i32 %1340; CHECK: @test_less-precise-fpmad2(i32 %i) [[FPMAD_FALSE]] {341; CHECK-NEXT: ret i32342}343 344define i32 @test_less-precise-fpmad3(i32 %i) "less-precise-fpmad"="true" {345 %1 = call i32 @less-precise-fpmad_callee1(i32 %i)346 ret i32 %1347; CHECK: @test_less-precise-fpmad3(i32 %i) [[FPMAD_TRUE]] {348; CHECK-NEXT: ret i32349}350 351define i32 @no-implicit-float_callee0(i32 %i) {352 ret i32 %i353; CHECK: @no-implicit-float_callee0(i32 %i) {354; CHECK-NEXT: ret i32355}356 357define i32 @no-implicit-float_callee1(i32 %i) noimplicitfloat {358 ret i32 %i359; CHECK: @no-implicit-float_callee1(i32 %i) [[NOIMPLICITFLOAT:#[0-9]+]] {360; CHECK-NEXT: ret i32361}362 363define i32 @test_no-implicit-float0(i32 %i) {364 %1 = call i32 @no-implicit-float_callee0(i32 %i)365 ret i32 %1366; CHECK: @test_no-implicit-float0(i32 %i) {367; CHECK-NEXT: ret i32368}369 370define i32 @test_no-implicit-float1(i32 %i) {371 %1 = call i32 @no-implicit-float_callee1(i32 %i)372 ret i32 %1373; CHECK: @test_no-implicit-float1(i32 %i) [[NOIMPLICITFLOAT]] {374; CHECK-NEXT: ret i32375}376 377define i32 @test_no-implicit-float2(i32 %i) noimplicitfloat {378 %1 = call i32 @no-implicit-float_callee0(i32 %i)379 ret i32 %1380; CHECK: @test_no-implicit-float2(i32 %i) [[NOIMPLICITFLOAT]] {381; CHECK-NEXT: ret i32382}383 384define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat {385 %1 = call i32 @no-implicit-float_callee1(i32 %i)386 ret i32 %1387; CHECK: @test_no-implicit-float3(i32 %i) [[NOIMPLICITFLOAT]] {388; CHECK-NEXT: ret i32389}390 391; Check that no-jump-tables flag propagates from inlined callee to caller392 393define i32 @no-use-jump-tables_callee0(i32 %i) {394 ret i32 %i395; CHECK: @no-use-jump-tables_callee0(i32 %i) {396; CHECK-NEXT: ret i32397}398 399define i32 @no-use-jump-tables_callee1(i32 %i) "no-jump-tables"="true" {400 ret i32 %i401; CHECK: @no-use-jump-tables_callee1(i32 %i) [[NOUSEJUMPTABLES:#[0-9]+]] {402; CHECK-NEXT: ret i32403}404 405define i32 @test_no-use-jump-tables0(i32 %i) {406 %1 = call i32 @no-use-jump-tables_callee0(i32 %i)407 ret i32 %1408; CHECK: @test_no-use-jump-tables0(i32 %i) {409; CHECK-NEXT: ret i32410}411 412define i32 @test_no-use-jump-tables1(i32 %i) {413 %1 = call i32 @no-use-jump-tables_callee1(i32 %i)414 ret i32 %1415; CHECK: @test_no-use-jump-tables1(i32 %i) [[NOUSEJUMPTABLES]] {416; CHECK-NEXT: ret i32417}418 419define i32 @test_no-use-jump-tables2(i32 %i) "no-jump-tables"="true" {420 %1 = call i32 @no-use-jump-tables_callee0(i32 %i)421 ret i32 %1422; CHECK: @test_no-use-jump-tables2(i32 %i) [[NOUSEJUMPTABLES]] {423; CHECK-NEXT: ret i32424}425 426define i32 @test_no-use-jump-tables3(i32 %i) "no-jump-tables"="true" {427 %1 = call i32 @no-use-jump-tables_callee1(i32 %i)428 ret i32 %1429; CHECK: @test_no-use-jump-tables3(i32 %i) [[NOUSEJUMPTABLES]] {430; CHECK-NEXT: ret i32431}432 433; Callee with null_pointer_is_valid attribute should not be inlined434; into a caller without this attribute.435; Exception: alwaysinline callee can still be inlined but436; null_pointer_is_valid should get copied to caller.437 438define i32 @null-pointer-is-valid_callee0(i32 %i) null_pointer_is_valid {439 ret i32 %i440; CHECK: @null-pointer-is-valid_callee0(i32 %i)441; CHECK-NEXT: ret i32442}443 444define i32 @null-pointer-is-valid_callee1(i32 %i) alwaysinline null_pointer_is_valid {445 ret i32 %i446; CHECK: @null-pointer-is-valid_callee1(i32 %i)447; CHECK-NEXT: ret i32448}449 450define i32 @null-pointer-is-valid_callee2(i32 %i) {451 ret i32 %i452; CHECK: @null-pointer-is-valid_callee2(i32 %i)453; CHECK-NEXT: ret i32454}455 456; No inlining since caller does not have null_pointer_is_valid attribute.457define i32 @test_null-pointer-is-valid0(i32 %i) {458 %1 = call i32 @null-pointer-is-valid_callee0(i32 %i)459 ret i32 %1460; CHECK: @test_null-pointer-is-valid0(461; CHECK: call i32 @null-pointer-is-valid_callee0462; CHECK-NEXT: ret i32463}464 465; alwaysinline should force inlining even when caller does not have466; null_pointer_is_valid attribute. However, the attribute should be467; copied to caller.468define i32 @test_null-pointer-is-valid1(i32 %i) {469 %1 = call i32 @null-pointer-is-valid_callee1(i32 %i)470 ret i32 %1471; CHECK: @test_null-pointer-is-valid1(i32 %i) [[NULLPOINTERISVALID:#[0-9]+]] {472; CHECK-NEXT: ret i32473}474 475; Can inline since both caller and callee have null_pointer_is_valid476; attribute.477define i32 @test_null-pointer-is-valid2(i32 %i) null_pointer_is_valid {478 %1 = call i32 @null-pointer-is-valid_callee2(i32 %i)479 ret i32 %1480; CHECK: @test_null-pointer-is-valid2(i32 %i) [[NULLPOINTERISVALID]] {481; CHECK-NEXT: ret i32482}483 484define i32 @no-infs-fp-math_callee0(i32 %i) "no-infs-fp-math"="false" {485 ret i32 %i486; CHECK: @no-infs-fp-math_callee0(i32 %i) [[NO_INFS_FPMATH_FALSE:#[0-9]+]] {487; CHECK-NEXT: ret i32488}489 490define i32 @no-infs-fp-math_callee1(i32 %i) "no-infs-fp-math"="true" {491 ret i32 %i492; CHECK: @no-infs-fp-math_callee1(i32 %i) [[NO_INFS_FPMATH_TRUE:#[0-9]+]] {493; CHECK-NEXT: ret i32494}495 496define i32 @test_no-infs-fp-math0(i32 %i) "no-infs-fp-math"="false" {497 %1 = call i32 @no-infs-fp-math_callee0(i32 %i)498 ret i32 %1499; CHECK: @test_no-infs-fp-math0(i32 %i) [[NO_INFS_FPMATH_FALSE]] {500; CHECK-NEXT: ret i32501}502 503define i32 @test_no-infs-fp-math1(i32 %i) "no-infs-fp-math"="false" {504 %1 = call i32 @no-infs-fp-math_callee1(i32 %i)505 ret i32 %1506; CHECK: @test_no-infs-fp-math1(i32 %i) [[NO_INFS_FPMATH_FALSE]] {507; CHECK-NEXT: ret i32508}509 510define i32 @test_no-infs-fp-math2(i32 %i) "no-infs-fp-math"="true" {511 %1 = call i32 @no-infs-fp-math_callee0(i32 %i)512 ret i32 %1513; CHECK: @test_no-infs-fp-math2(i32 %i) [[NO_INFS_FPMATH_FALSE]] {514; CHECK-NEXT: ret i32515}516 517define i32 @test_no-infs-fp-math3(i32 %i) "no-infs-fp-math"="true" {518 %1 = call i32 @no-infs-fp-math_callee1(i32 %i)519 ret i32 %1520; CHECK: @test_no-infs-fp-math3(i32 %i) [[NO_INFS_FPMATH_TRUE]] {521; CHECK-NEXT: ret i32522}523 524define i32 @no-nans-fp-math_callee0(i32 %i) "no-nans-fp-math"="false" {525 ret i32 %i526; CHECK: @no-nans-fp-math_callee0(i32 %i) [[NO_NANS_FPMATH_FALSE:#[0-9]+]] {527; CHECK-NEXT: ret i32528}529 530define i32 @no-nans-fp-math_callee1(i32 %i) "no-nans-fp-math"="true" {531 ret i32 %i532; CHECK: @no-nans-fp-math_callee1(i32 %i) [[NO_NANS_FPMATH_TRUE:#[0-9]+]] {533; CHECK-NEXT: ret i32534}535 536define i32 @test_no-nans-fp-math0(i32 %i) "no-nans-fp-math"="false" {537 %1 = call i32 @no-nans-fp-math_callee0(i32 %i)538 ret i32 %1539; CHECK: @test_no-nans-fp-math0(i32 %i) [[NO_NANS_FPMATH_FALSE]] {540; CHECK-NEXT: ret i32541}542 543define i32 @test_no-nans-fp-math1(i32 %i) "no-nans-fp-math"="false" {544 %1 = call i32 @no-nans-fp-math_callee1(i32 %i)545 ret i32 %1546; CHECK: @test_no-nans-fp-math1(i32 %i) [[NO_NANS_FPMATH_FALSE]] {547; CHECK-NEXT: ret i32548}549 550define i32 @test_no-nans-fp-math2(i32 %i) "no-nans-fp-math"="true" {551 %1 = call i32 @no-nans-fp-math_callee0(i32 %i)552 ret i32 %1553; CHECK: @test_no-nans-fp-math2(i32 %i) [[NO_NANS_FPMATH_FALSE]] {554; CHECK-NEXT: ret i32555}556 557define i32 @test_no-nans-fp-math3(i32 %i) "no-nans-fp-math"="true" {558 %1 = call i32 @no-nans-fp-math_callee1(i32 %i)559 ret i32 %1560; CHECK: @test_no-nans-fp-math3(i32 %i) [[NO_NANS_FPMATH_TRUE]] {561; CHECK-NEXT: ret i32562}563 564define i32 @no-signed-zeros-fp-math_callee0(i32 %i) "no-signed-zeros-fp-math"="false" {565 ret i32 %i566; CHECK: @no-signed-zeros-fp-math_callee0(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_FALSE:#[0-9]+]] {567; CHECK-NEXT: ret i32568}569 570define i32 @no-signed-zeros-fp-math_callee1(i32 %i) "no-signed-zeros-fp-math"="true" {571 ret i32 %i572; CHECK: @no-signed-zeros-fp-math_callee1(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_TRUE:#[0-9]+]] {573; CHECK-NEXT: ret i32574}575 576define i32 @test_no-signed-zeros-fp-math0(i32 %i) "no-signed-zeros-fp-math"="false" {577 %1 = call i32 @no-signed-zeros-fp-math_callee0(i32 %i)578 ret i32 %1579; CHECK: @test_no-signed-zeros-fp-math0(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_FALSE]] {580; CHECK-NEXT: ret i32581}582 583define i32 @test_no-signed-zeros-fp-math1(i32 %i) "no-signed-zeros-fp-math"="false" {584 %1 = call i32 @no-signed-zeros-fp-math_callee1(i32 %i)585 ret i32 %1586; CHECK: @test_no-signed-zeros-fp-math1(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_FALSE]] {587; CHECK-NEXT: ret i32588}589 590define i32 @test_no-signed-zeros-fp-math2(i32 %i) "no-signed-zeros-fp-math"="true" {591 %1 = call i32 @no-signed-zeros-fp-math_callee0(i32 %i)592 ret i32 %1593; CHECK: @test_no-signed-zeros-fp-math2(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_FALSE]] {594; CHECK-NEXT: ret i32595}596 597define i32 @test_no-signed-zeros-fp-math3(i32 %i) "no-signed-zeros-fp-math"="true" {598 %1 = call i32 @no-signed-zeros-fp-math_callee1(i32 %i)599 ret i32 %1600; CHECK: @test_no-signed-zeros-fp-math3(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_TRUE]] {601; CHECK-NEXT: ret i32602}603 604; Test that fn_ret_thunk_extern has no CompatRule; inlining is permitted.605; Test that fn_ret_thunk_extern has no MergeRule; fn_ret_thunk_extern is not606; propagated or dropped on the caller after inlining.607define i32 @thunk_extern_callee() fn_ret_thunk_extern {608; CHECK: @thunk_extern_callee() [[FNRETTHUNK_EXTERN:#[0-9]+]]609 ret i32 42610}611 612define i32 @thunk_keep_caller() {613; CHECK: @thunk_keep_caller() {614; CHECK-NEXT: ret i32 42615 %1 = call i32 @thunk_extern_callee()616 ret i32 %1617}618 619define i32 @thunk_keep_callee() {620; CHECK: @thunk_keep_callee() {621 ret i32 42622}623 624define i32 @thunk_extern_caller() fn_ret_thunk_extern {625; CHECK: @thunk_extern_caller() [[FNRETTHUNK_EXTERN]]626; CHECK-NEXT: ret i32 42627 %1 = call i32 @thunk_keep_callee()628 ret i32 %1629}630 631; Test that loader replaceable functions never get inlined.632define i32 @loader_replaceable_callee(i32 %i) "loader-replaceable" {633 ret i32 %i634}635 636define i32 @loader_replaceable_caller() {637; CHECK: @loader_replaceable_caller() {638; CHECK-NEXT: call i32 @loader_replaceable_callee()639 %1 = call i32 @loader_replaceable_callee()640 ret i32 %1641}642 643; CHECK: attributes [[SANITIZE_ALLOC_TOKEN]] = { sanitize_alloc_token }644; CHECK: attributes [[SLH]] = { speculative_load_hardening }645; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" }646; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" }647; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat }648; CHECK: attributes [[NOUSEJUMPTABLES]] = { "no-jump-tables"="true" }649; CHECK: attributes [[NULLPOINTERISVALID]] = { null_pointer_is_valid }650; CHECK: attributes [[NO_INFS_FPMATH_FALSE]] = { "no-infs-fp-math"="false" }651; CHECK: attributes [[NO_INFS_FPMATH_TRUE]] = { "no-infs-fp-math"="true" }652; CHECK: attributes [[NO_NANS_FPMATH_FALSE]] = { "no-nans-fp-math"="false" }653; CHECK: attributes [[NO_NANS_FPMATH_TRUE]] = { "no-nans-fp-math"="true" }654; CHECK: attributes [[NO_SIGNED_ZEROS_FPMATH_FALSE]] = { "no-signed-zeros-fp-math"="false" }655; CHECK: attributes [[NO_SIGNED_ZEROS_FPMATH_TRUE]] = { "no-signed-zeros-fp-math"="true" }656; CHECK: attributes [[FNRETTHUNK_EXTERN]] = { fn_ret_thunk_extern }657