1 ; RUN: opt < %s -inline -S | FileCheck %s 2 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" 3 4 define i32 @noattr_callee(i32 %i) { 5 ret i32 %i 6 } 7 8 define i32 @sanitize_address_callee(i32 %i) sanitize_address { 9 ret i32 %i 10 } 11 12 define i32 @sanitize_thread_callee(i32 %i) sanitize_thread { 13 ret i32 %i 14 } 15 16 define i32 @sanitize_memory_callee(i32 %i) sanitize_memory { 17 ret i32 %i 18 } 19 20 define i32 @safestack_callee(i32 %i) safestack { 21 ret i32 %i 22 } 23 24 define i32 @alwaysinline_callee(i32 %i) alwaysinline { 25 ret i32 %i 26 } 27 28 define i32 @alwaysinline_sanitize_address_callee(i32 %i) alwaysinline sanitize_address { 29 ret i32 %i 30 } 31 32 define i32 @alwaysinline_sanitize_thread_callee(i32 %i) alwaysinline sanitize_thread { 33 ret i32 %i 34 } 35 36 define i32 @alwaysinline_sanitize_memory_callee(i32 %i) alwaysinline sanitize_memory { 37 ret i32 %i 38 } 39 40 define 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 50 define 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 61 define 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 72 define 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 89 define 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 100 define 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 111 define 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 122 define 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. 135 define i32 @test_target_cpu_callee0(i32 %i) "target-cpu"="corei7" { 136 ret i32 %i 137 } 138 139 define 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 146 define i32 @test_target_cpu_callee1(i32 %i) "target-cpu"="x86-64" { 147 ret i32 %i 148 } 149 150 define 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. 160 define i32 @test_target_features_callee0(i32 %i) "target-features"="+sse4.2" { 161 ret i32 %i 162 } 163 164 define 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 171 define i32 @test_target_features_callee1(i32 %i) "target-features"="+avx2" { 172 ret i32 %i 173 } 174 175 define 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 183 define 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 189 define 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 195 define 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 202 define 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 209 define 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 216 define 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 223 define 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 229 define 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 235 define 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 242 define 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 249 define 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 256 define 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 265 define 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 271 define 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 277 define 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 284 define 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 291 define 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 298 define 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" }