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