1// RUN: mlir-opt -split-input-file -verify-diagnostics %s | mlir-opt | FileCheck %s 2// RUN: mlir-opt -split-input-file -verify-diagnostics -mlir-print-op-generic %s | FileCheck %s --check-prefix=GENERIC 3// RUN: mlir-opt -split-input-file -verify-diagnostics -mlir-print-debuginfo %s | mlir-opt -split-input-file -mlir-print-debuginfo | FileCheck %s --check-prefix=LOCINFO 4// RUN: mlir-translate -mlir-to-llvmir -split-input-file -verify-diagnostics %s | FileCheck %s --check-prefix=CHECK-LLVM 5 6module { 7 // GENERIC: "llvm.func" 8 // GENERIC-SAME: function_type = !llvm.func<void ()> 9 // GENERIC-SAME: sym_name = "foo" 10 // GENERIC: () -> () 11 // CHECK: llvm.func @foo() 12 "llvm.func" () ({ 13 }) {sym_name = "foo", function_type = !llvm.func<void ()>} : () -> () 14 15 // GENERIC: "llvm.func" 16 // GENERIC-SAME: function_type = !llvm.func<i64 (i64, i64)> 17 // GENERIC-SAME: sym_name = "bar" 18 // GENERIC: () -> () 19 // CHECK: llvm.func @bar(i64, i64) -> i64 20 "llvm.func"() ({ 21 }) {sym_name = "bar", function_type = !llvm.func<i64 (i64, i64)>} : () -> () 22 23 // GENERIC: "llvm.func" 24 // GENERIC-SAME: function_type = !llvm.func<i64 (i64)> 25 // GENERIC-SAME: sym_name = "baz" 26 // CHECK: llvm.func @baz(%{{.*}}: i64) -> i64 27 "llvm.func"() <{sym_name = "baz", function_type = !llvm.func<i64 (i64)>}> ({ 28 // GENERIC: ^bb0 29 ^bb0(%arg0: i64): 30 // GENERIC: llvm.return 31 llvm.return %arg0 : i64 32 33 // GENERIC: () -> () 34 }) : () -> () 35 36 // CHECK: llvm.func @qux(!llvm.ptr {llvm.noalias}, i64) 37 // CHECK: attributes {xxx = {yyy = 42 : i64}} 38 "llvm.func"() ({ 39 }) {sym_name = "qux", function_type = !llvm.func<void (ptr, i64)>, 40 arg_attrs = [{llvm.noalias}, {}], xxx = {yyy = 42}} : () -> () 41 42 // CHECK: llvm.func @roundtrip1() 43 llvm.func @roundtrip1() 44 45 // CHECK: llvm.func @roundtrip2(i64, f32) -> f64 46 llvm.func @roundtrip2(i64, f32) -> f64 47 48 // CHECK: llvm.func @roundtrip3(i32, i1) 49 llvm.func @roundtrip3(%a: i32, %b: i1) 50 51 // CHECK: llvm.func @roundtrip4(%{{.*}}: i32, %{{.*}}: i1) { 52 llvm.func @roundtrip4(%a: i32, %b: i1) { 53 llvm.return 54 } 55 56 // CHECK: llvm.func @roundtrip5() 57 // CHECK: attributes {baz = 42 : i64, foo = "bar"} 58 llvm.func @roundtrip5() attributes {foo = "bar", baz = 42} 59 60 // CHECK: llvm.func @roundtrip6() 61 // CHECK: attributes {baz = 42 : i64, foo = "bar"} 62 llvm.func @roundtrip6() attributes {foo = "bar", baz = 42} { 63 llvm.return 64 } 65 66 // CHECK: llvm.func @roundtrip7() { 67 llvm.func @roundtrip7() attributes {} { 68 llvm.return 69 } 70 71 // CHECK: llvm.func @roundtrip8() -> i32 72 llvm.func @roundtrip8() -> i32 attributes {} 73 74 // CHECK: llvm.func @roundtrip9(!llvm.ptr {llvm.noalias}) 75 llvm.func @roundtrip9(!llvm.ptr {llvm.noalias}) 76 77 // CHECK: llvm.func @roundtrip10(!llvm.ptr {llvm.noalias}) 78 llvm.func @roundtrip10(%arg0: !llvm.ptr {llvm.noalias}) 79 80 // CHECK: llvm.func @roundtrip11(%{{.*}}: !llvm.ptr {llvm.noalias}) { 81 llvm.func @roundtrip11(%arg0: !llvm.ptr {llvm.noalias}) { 82 llvm.return 83 } 84 85 // CHECK: llvm.func @roundtrip12(%{{.*}}: !llvm.ptr {llvm.noalias}) 86 // CHECK: attributes {foo = 42 : i32} 87 llvm.func @roundtrip12(%arg0: !llvm.ptr {llvm.noalias}) 88 attributes {foo = 42 : i32} { 89 llvm.return 90 } 91 92 // CHECK: llvm.func @byvalattr(%{{.*}}: !llvm.ptr {llvm.byval = i32}) 93 llvm.func @byvalattr(%arg0: !llvm.ptr {llvm.byval = i32}) { 94 llvm.return 95 } 96 97 // CHECK: llvm.func @sretattr(%{{.*}}: !llvm.ptr {llvm.sret = i32}) 98 // LOCINFO: llvm.func @sretattr(%{{.*}}: !llvm.ptr {llvm.sret = i32} loc("some_source_loc")) 99 llvm.func @sretattr(%arg0: !llvm.ptr {llvm.sret = i32} loc("some_source_loc")) { 100 llvm.return 101 } 102 103 // CHECK: llvm.func @nestattr(%{{.*}}: !llvm.ptr {llvm.nest}) 104 llvm.func @nestattr(%arg0: !llvm.ptr {llvm.nest}) { 105 llvm.return 106 } 107 108 // CHECK: llvm.func @llvm_noalias_decl(!llvm.ptr {llvm.noalias}) 109 llvm.func @llvm_noalias_decl(!llvm.ptr {llvm.noalias}) 110 // CHECK: llvm.func @byrefattr_decl(!llvm.ptr {llvm.byref = i32}) 111 llvm.func @byrefattr_decl(!llvm.ptr {llvm.byref = i32}) 112 // CHECK: llvm.func @byvalattr_decl(!llvm.ptr {llvm.byval = i32}) 113 llvm.func @byvalattr_decl(!llvm.ptr {llvm.byval = i32}) 114 // CHECK: llvm.func @sretattr_decl(!llvm.ptr {llvm.sret = i32}) 115 llvm.func @sretattr_decl(!llvm.ptr {llvm.sret = i32}) 116 // CHECK: llvm.func @nestattr_decl(!llvm.ptr {llvm.nest}) 117 llvm.func @nestattr_decl(!llvm.ptr {llvm.nest}) 118 // CHECK: llvm.func @noundefattr_decl(i32 {llvm.noundef}) 119 llvm.func @noundefattr_decl(i32 {llvm.noundef}) 120 // CHECK: llvm.func @llvm_align_decl(!llvm.ptr {llvm.align = 4 : i64}) 121 llvm.func @llvm_align_decl(!llvm.ptr {llvm.align = 4}) 122 // CHECK: llvm.func @inallocaattr_decl(!llvm.ptr {llvm.inalloca = i32}) 123 llvm.func @inallocaattr_decl(!llvm.ptr {llvm.inalloca = i32}) 124 125 126 // CHECK: llvm.func @variadic(...) 127 llvm.func @variadic(...) 128 129 // CHECK: llvm.func @variadic_args(i32, i32, ...) 130 llvm.func @variadic_args(i32, i32, ...) 131 132 // 133 // Check that functions can have linkage attributes. 134 // 135 136 // CHECK: llvm.func internal 137 llvm.func internal @internal_func() { 138 llvm.return 139 } 140 141 // CHECK: llvm.func weak 142 llvm.func weak @weak_linkage() { 143 llvm.return 144 } 145 146 // CHECK-LLVM: define ptx_kernel void @calling_conv 147 llvm.func ptx_kernelcc @calling_conv() { 148 llvm.return 149 } 150 151 // Omit the `external` linkage, which is the default, in the custom format. 152 // Check that it is present in the generic format using its numeric value. 153 // 154 // CHECK: llvm.func @external_func 155 // GENERIC: linkage = #llvm.linkage<external> 156 llvm.func external @external_func() 157 158 // CHECK-LABEL: llvm.func @arg_struct_attr( 159 // CHECK-SAME: %{{.*}}: !llvm.struct<(i32)> {llvm.struct_attrs = [{llvm.noalias}]}) { 160 llvm.func @arg_struct_attr( 161 %arg0 : !llvm.struct<(i32)> {llvm.struct_attrs = [{llvm.noalias}]}) { 162 llvm.return 163 } 164 165 // CHECK-LABEL: llvm.func @res_struct_attr(%{{.*}}: !llvm.struct<(i32)>) 166 // CHECK-SAME:-> (!llvm.struct<(i32)> {llvm.struct_attrs = [{llvm.noalias}]}) { 167 llvm.func @res_struct_attr(%arg0 : !llvm.struct<(i32)>) 168 -> (!llvm.struct<(i32)> {llvm.struct_attrs = [{llvm.noalias}]}) { 169 llvm.return %arg0 : !llvm.struct<(i32)> 170 } 171 172 // CHECK: llvm.func @cconv1 173 llvm.func ccc @cconv1() { 174 llvm.return 175 } 176 177 // CHECK: llvm.func weak @cconv2 178 llvm.func weak ccc @cconv2() { 179 llvm.return 180 } 181 182 // CHECK: llvm.func weak fastcc @cconv3 183 llvm.func weak fastcc @cconv3() { 184 llvm.return 185 } 186 187 // CHECK: llvm.func cc_10 @cconv4 188 llvm.func cc_10 @cconv4() { 189 llvm.return 190 } 191 192 // CHECK: llvm.func @test_ccs 193 llvm.func @test_ccs() { 194 // CHECK-NEXT: %[[PTR:.*]] = llvm.mlir.addressof @cconv4 : !llvm.ptr 195 %ptr = llvm.mlir.addressof @cconv4 : !llvm.ptr 196 // CHECK-NEXT: llvm.call @cconv1() : () -> () 197 // CHECK-NEXT: llvm.call @cconv2() : () -> () 198 // CHECK-NEXT: llvm.call fastcc @cconv3() : () -> () 199 // CHECK-NEXT: llvm.call cc_10 %[[PTR]]() : !llvm.ptr, () -> () 200 llvm.call @cconv1() : () -> () 201 llvm.call ccc @cconv2() : () -> () 202 llvm.call fastcc @cconv3() : () -> () 203 llvm.call cc_10 %ptr() : !llvm.ptr, () -> () 204 llvm.return 205 } 206 207 // CHECK-LABEL: llvm.func @variadic_def 208 llvm.func @variadic_def(...) { 209 llvm.return 210 } 211 212 // CHECK-LABEL: llvm.func @memory_attr 213 // CHECK-SAME: attributes {memory = #llvm.memory_effects<other = none, argMem = read, inaccessibleMem = readwrite>} { 214 llvm.func @memory_attr() attributes {memory = #llvm.memory_effects<other = none, argMem = read, inaccessibleMem = readwrite>} { 215 llvm.return 216 } 217 218 // CHECK-LABEL: llvm.func hidden @hidden 219 llvm.func hidden @hidden() { 220 llvm.return 221 } 222 223 // CHECK-LABEL: llvm.func protected @protected 224 llvm.func protected @protected() { 225 llvm.return 226 } 227 228 // CHECK-LABEL: local_unnamed_addr @local_unnamed_addr_func 229 llvm.func local_unnamed_addr @local_unnamed_addr_func() { 230 llvm.return 231 } 232 233 // CHECK-LABEL: @align_func 234 // CHECK-SAME: attributes {alignment = 2 : i64} 235 llvm.func @align_func() attributes {alignment = 2 : i64} { 236 llvm.return 237 } 238 239 // CHECK: llvm.comdat @__llvm_comdat 240 llvm.comdat @__llvm_comdat { 241 // CHECK: llvm.comdat_selector @any any 242 llvm.comdat_selector @any any 243 } 244 // CHECK: @any() comdat(@__llvm_comdat::@any) attributes 245 llvm.func @any() comdat(@__llvm_comdat::@any) attributes { dso_local } { 246 llvm.return 247 } 248 249 llvm.func @vscale_roundtrip() vscale_range(1, 2) { 250 // CHECK: @vscale_roundtrip 251 // CHECK-SAME: vscale_range(1, 2) 252 llvm.return 253 } 254 255 // CHECK-LABEL: @frame_pointer_roundtrip() 256 // CHECK-SAME: attributes {frame_pointer = #llvm.framePointerKind<"non-leaf">} 257 llvm.func @frame_pointer_roundtrip() attributes {frame_pointer = #llvm.framePointerKind<"non-leaf">} { 258 llvm.return 259 } 260 261 llvm.func @unsafe_fp_math_roundtrip() attributes {unsafe_fp_math = true} { 262 // CHECK: @unsafe_fp_math_roundtrip 263 // CHECK-SAME: attributes {unsafe_fp_math = true} 264 llvm.return 265 } 266 267 llvm.func @no_infs_fp_math_roundtrip() attributes {no_infs_fp_math = true} { 268 // CHECK: @no_infs_fp_math_roundtrip 269 // CHECK-SAME: attributes {no_infs_fp_math = true} 270 llvm.return 271 } 272 273 llvm.func @no_nans_fp_math_roundtrip() attributes {no_nans_fp_math = true} { 274 // CHECK: @no_nans_fp_math_roundtrip 275 // CHECK-SAME: attributes {no_nans_fp_math = true} 276 llvm.return 277 } 278 279 llvm.func @approx_func_fp_math_roundtrip() attributes {approx_func_fp_math = true} { 280 // CHECK: @approx_func_fp_math_roundtrip 281 // CHECK-SAME: attributes {approx_func_fp_math = true} 282 llvm.return 283 } 284 285 llvm.func @no_signed_zeros_fp_math_roundtrip() attributes {no_signed_zeros_fp_math = true} { 286 // CHECK: @no_signed_zeros_fp_math_roundtrip 287 // CHECK-SAME: attributes {no_signed_zeros_fp_math = true} 288 llvm.return 289 } 290 291 llvm.func @convergent_function() attributes {convergent} { 292 // CHECK: @convergent_function 293 // CHECK-SAME: attributes {convergent} 294 llvm.return 295 } 296 297 llvm.func @denormal_fp_math_roundtrip() attributes {denormal_fp_math = "preserve-sign"} { 298 // CHECK: @denormal_fp_math_roundtrip 299 // CHECK-SAME: attributes {denormal_fp_math = "preserve-sign"} 300 llvm.return 301 } 302 303 llvm.func @denormal_fp_math_f32_roundtrip() attributes {denormal_fp_math_f32 = "preserve-sign"} { 304 // CHECK: @denormal_fp_math_f32_roundtrip 305 // CHECK-SAME: attributes {denormal_fp_math_f32 = "preserve-sign"} 306 llvm.return 307 } 308 309 llvm.func @fp_contract_roundtrip() attributes {fp_contract = "fast"} { 310 // CHECK: @fp_contract_roundtrip 311 // CHECK-SAME: attributes {fp_contract = "fast"} 312 llvm.return 313 } 314 315 llvm.func @nounwind_function() attributes {no_unwind} { 316 // CHECK: @nounwind_function 317 // CHECK-SAME: attributes {no_unwind} 318 llvm.return 319 } 320 321 llvm.func @willreturn_function() attributes {will_return} { 322 // CHECK: @willreturn_function 323 // CHECK-SAME: attributes {will_return} 324 llvm.return 325 } 326 327 328} 329 330// ----- 331 332module { 333 // expected-error@+1 {{requires one region}} 334 "llvm.func"() {function_type = !llvm.func<void ()>, sym_name = "no_region"} : () -> () 335} 336 337// ----- 338 339module { 340 // expected-error@+1 {{requires attribute 'function_type'}} 341 "llvm.func"() ({}) {sym_name = "missing_type"} : () -> () 342} 343 344// ----- 345 346module { 347 // expected-error@+1 {{attribute 'function_type' failed to satisfy constraint: type attribute of LLVM function type}} 348 "llvm.func"() ({}) {sym_name = "non_llvm_type", function_type = i64} : () -> () 349} 350 351// ----- 352 353module { 354 // expected-error@+1 {{attribute 'function_type' failed to satisfy constraint: type attribute of LLVM function type}} 355 "llvm.func"() ({}) {sym_name = "non_function_type", function_type = i64} : () -> () 356} 357 358// ----- 359 360module { 361 // expected-error@+1 {{entry block must have 0 arguments}} 362 "llvm.func"() ({ 363 ^bb0(%arg0: i64): 364 llvm.return 365 }) {function_type = !llvm.func<void ()>, sym_name = "wrong_arg_number"} : () -> () 366} 367 368// ----- 369 370module { 371 // expected-error@+1 {{entry block argument #0('tensor<*xf32>') must match the type of the corresponding argument in function signature('i64')}} 372 "llvm.func"() ({ 373 ^bb0(%arg0: tensor<*xf32>): 374 llvm.return 375 }) {function_type = !llvm.func<void (i64)>, sym_name = "wrong_arg_number"} : () -> () 376} 377 378// ----- 379 380module { 381 // expected-error@+1 {{failed to construct function type: expected LLVM type for function arguments}} 382 llvm.func @foo(tensor<*xf32>) 383} 384 385// ----- 386 387module { 388 // expected-error@+1 {{failed to construct function type: expected LLVM type for function results}} 389 llvm.func @foo() -> tensor<*xf32> 390} 391 392// ----- 393 394module { 395 // expected-error@+1 {{failed to construct function type: expected zero or one function result}} 396 llvm.func @foo() -> (i64, i64) 397} 398 399// ----- 400 401module { 402 // expected-error@+1 {{variadic arguments must be in the end of the argument list}} 403 llvm.func @variadic_inside(%arg0: i32, ..., %arg1: i32) 404} 405 406// ----- 407 408module { 409 // expected-error@+1 {{external functions must have 'external' or 'extern_weak' linkage}} 410 llvm.func internal @internal_external_func() 411} 412 413// ----- 414 415module { 416 // expected-error@+1 {{functions cannot have 'common' linkage}} 417 llvm.func common @common_linkage_func() 418} 419 420// ----- 421 422module { 423 // expected-error@+1 {{custom op 'llvm.func' expected valid '@'-identifier for symbol name}} 424 llvm.func cc_12 @unknown_calling_convention() 425} 426 427// ----- 428 429module { 430 "llvm.func"() ({ 431 // expected-error @below {{invalid Calling Conventions specification: cc_12}} 432 // expected-error @below {{failed to parse CConvAttr parameter 'CallingConv' which is to be a `CConv`}} 433 }) {sym_name = "generic_unknown_calling_convention", CConv = #llvm.cconv<cc_12>, function_type = !llvm.func<i64 (i64, i64)>} : () -> () 434} 435 436// ----- 437 438// CHECK: @vec_type_hint() 439// CHECK-SAME: vec_type_hint = #llvm.vec_type_hint<hint = i32> 440llvm.func @vec_type_hint() attributes {vec_type_hint = #llvm.vec_type_hint<hint = i32>} 441 442// CHECK: @vec_type_hint_signed() 443// CHECK-SAME: vec_type_hint = #llvm.vec_type_hint<hint = i32, is_signed = true> 444llvm.func @vec_type_hint_signed() attributes {vec_type_hint = #llvm.vec_type_hint<hint = i32, is_signed = true>} 445 446// CHECK: @vec_type_hint_signed_vec() 447// CHECK-SAME: vec_type_hint = #llvm.vec_type_hint<hint = vector<2xi32>, is_signed = true> 448llvm.func @vec_type_hint_signed_vec() attributes {vec_type_hint = #llvm.vec_type_hint<hint = vector<2xi32>, is_signed = true>} 449 450// CHECK: @vec_type_hint_float_vec() 451// CHECK-SAME: vec_type_hint = #llvm.vec_type_hint<hint = vector<3xf32>> 452llvm.func @vec_type_hint_float_vec() attributes {vec_type_hint = #llvm.vec_type_hint<hint = vector<3xf32>>} 453 454// CHECK: @vec_type_hint_bfloat_vec() 455// CHECK-SAME: vec_type_hint = #llvm.vec_type_hint<hint = vector<8xbf16>> 456llvm.func @vec_type_hint_bfloat_vec() attributes {vec_type_hint = #llvm.vec_type_hint<hint = vector<8xbf16>>} 457 458// ----- 459 460// CHECK: @work_group_size_hint() 461// CHECK-SAME: work_group_size_hint = array<i32: 128, 128, 128> 462llvm.func @work_group_size_hint() attributes {work_group_size_hint = array<i32: 128, 128, 128>} 463 464// ----- 465 466// CHECK: @reqd_work_group_size_hint() 467// CHECK-SAME: reqd_work_group_size = array<i32: 128, 256, 128> 468llvm.func @reqd_work_group_size_hint() attributes {reqd_work_group_size = array<i32: 128, 256, 128>} 469 470// ----- 471 472// CHECK: @intel_reqd_sub_group_size_hint() 473// CHECK-SAME: intel_reqd_sub_group_size = 32 : i32 474llvm.func @intel_reqd_sub_group_size_hint() attributes {llvm.intel_reqd_sub_group_size = 32 : i32} 475 476// ----- 477 478// CHECK: @workgroup_attribution 479// CHECK-SAME: llvm.workgroup_attribution = #llvm.mlir.workgroup_attribution<512 : i64, i32> 480// CHECK-SAME: llvm.workgroup_attribution = #llvm.mlir.workgroup_attribution<128 : i64, !llvm.struct<(i32, i64, f32)> 481llvm.func @workgroup_attribution(%arg0: !llvm.ptr {llvm.workgroup_attribution = #llvm.mlir.workgroup_attribution<512 : i64, i32>}, %arg1: !llvm.ptr {llvm.workgroup_attribution = #llvm.mlir.workgroup_attribution<128 : i64, !llvm.struct<(i32, i64, f32)>>}) 482 483// ----- 484 485// CHECK: @constant_range_negative 486// CHECK-SAME: llvm.range = #llvm.constant_range<i32, 0, -2147483648> 487llvm.func @constant_range_negative() -> (i32 {llvm.range = #llvm.constant_range<i32, 0, -2147483648>}) 488