// RUN: mlir-opt %s --irdl-file=%S/testd.irdl.mlir -split-input-file -verify-diagnostics | FileCheck %s
//===----------------------------------------------------------------------===//
// Type or attribute constraint
//===----------------------------------------------------------------------===//
func.func @typeFitsType() {
// CHECK: "testd.any"() : () -> !testd.parametric<i32>
"testd.any"() : () -> !testd.parametric<i32>
return
}
// -----
func.func @attrDoesntFitType() {
"testd.any"() : () -> !testd.parametric<"foo">
return
}
// -----
func.func @attrFitsAttr() {
// CHECK: "testd.any"() : () -> !testd.attr_in_type_out<"foo">
"testd.any"() : () -> !testd.attr_in_type_out<"foo">
return
}
// -----
func.func @typeFitsAttr() {
// CHECK: "testd.any"() : () -> !testd.attr_in_type_out<i32>
"testd.any"() : () -> !testd.attr_in_type_out<i32>
return
}
// -----
//===----------------------------------------------------------------------===//
// Equality constraint
//===----------------------------------------------------------------------===//
func.func @succeededEqConstraint() {
// CHECK: "testd.eq"() : () -> i32
"testd.eq"() : () -> i32
return
}
// -----
func.func @failedEqConstraint() {
// expected-error@+1 {{expected 'i32' but got 'i64'}}
"testd.eq"() : () -> i64
return
}
// -----
//===----------------------------------------------------------------------===//
// AnyOf constraint
//===----------------------------------------------------------------------===//
func.func @succeededAnyOfConstraint() {
// CHECK: "testd.anyof"() : () -> i32
"testd.anyof"() : () -> i32
// CHECK: "testd.anyof"() : () -> i64
"testd.anyof"() : () -> i64
return
}
// -----
func.func @failedAnyOfConstraint() {
// expected-error@+1 {{'i1' does not satisfy the constraint}}
"testd.anyof"() : () -> i1
return
}
// -----
//===----------------------------------------------------------------------===//
// AllOf constraint
//===----------------------------------------------------------------------===//
func.func @succeededAllOfConstraint() {
// CHECK: "testd.all_of"() : () -> i64
"testd.all_of"() : () -> i64
return
}
// -----
func.func @failedAllOfConstraint1() {
// expected-error@+1 {{'i1' does not satisfy the constraint}}
"testd.all_of"() : () -> i1
return
}
// -----
func.func @failedAllOfConstraint2() {
// expected-error@+1 {{expected 'i64' but got 'i32'}}
"testd.all_of"() : () -> i32
return
}
// -----
//===----------------------------------------------------------------------===//
// Any constraint
//===----------------------------------------------------------------------===//
func.func @succeededAnyConstraint() {
// CHECK: "testd.any"() : () -> i32
"testd.any"() : () -> i32
// CHECK: "testd.any"() : () -> i64
"testd.any"() : () -> i64
return
}
// -----
//===----------------------------------------------------------------------===//
// Base constraints
//===----------------------------------------------------------------------===//
func.func @succeededDynBaseConstraint() {
// CHECK: "testd.dyn_type_base"() : () -> !testd.parametric<i32>
"testd.dyn_type_base"() : () -> !testd.parametric<i32>
// CHECK: "testd.dyn_type_base"() : () -> !testd.parametric<i64>
"testd.dyn_type_base"() : () -> !testd.parametric<i64>
// CHECK: "testd.dyn_type_base"() : () -> !testd.parametric<!testd.parametric<i64>>
"testd.dyn_type_base"() : () -> !testd.parametric<!testd.parametric<i64>>
// CHECK: "testd.dyn_attr_base"() {attr1 = #testd.parametric_attr<i32>} : () -> ()
"testd.dyn_attr_base"() {attr1 = #testd.parametric_attr<i32>} : () -> ()
// CHECK: "testd.dyn_attr_base"() {attr1 = #testd.parametric_attr<i64>} : () -> ()
"testd.dyn_attr_base"() {attr1 = #testd.parametric_attr<i64>} : () -> ()
return
}
// -----
func.func @failedDynTypeBaseConstraint() {
// expected-error@+1 {{expected base type 'testd.parametric' but got 'builtin.integer'}}
"testd.dyn_type_base"() : () -> i32
return
}
// -----
func.func @failedDynAttrBaseConstraintNotType() {
// expected-error@+1 {{expected base attribute 'testd.parametric_attr' but got 'builtin.type'}}
"testd.dyn_attr_base"() {attr1 = i32}: () -> ()
return
}
// -----
func.func @succeededNamedBaseConstraint() {
// CHECK: "testd.named_type_base"() : () -> i32
"testd.named_type_base"() : () -> i32
// CHECK: "testd.named_type_base"() : () -> i64
"testd.named_type_base"() : () -> i64
// CHECK: "testd.named_attr_base"() {attr1 = 0 : i32} : () -> ()
"testd.named_attr_base"() {attr1 = 0 : i32} : () -> ()
// CHECK: "testd.named_attr_base"() {attr1 = 0 : i64} : () -> ()
"testd.named_attr_base"() {attr1 = 0 : i64} : () -> ()
return
}
// -----
func.func @failedNamedTypeBaseConstraint() {
// expected-error@+1 {{expected base type 'builtin.integer' but got 'builtin.vector'}}
"testd.named_type_base"() : () -> vector<i32>
return
}
// -----
func.func @failedDynAttrBaseConstraintNotType() {
// expected-error@+1 {{expected base attribute 'builtin.integer' but got 'builtin.type'}}
"testd.named_attr_base"() {attr1 = i32}: () -> ()
return
}
// -----
//===----------------------------------------------------------------------===//
// Dynamic parameters constraint
//===----------------------------------------------------------------------===//
func.func @succeededDynParamsConstraint() {
// CHECK: "testd.dynparams"() : () -> !testd.parametric<i32>
"testd.dynparams"() : () -> !testd.parametric<i32>
// CHECK: "testd.dynparams"() : () -> !testd.parametric<i64>
"testd.dynparams"() : () -> !testd.parametric<i64>
return
}
// -----
func.func @failedDynParamsConstraintBase() {
// expected-error@+1 {{expected base type 'testd.parametric' but got 'i32'}}
"testd.dynparams"() : () -> i32
return
}
// -----
func.func @failedDynParamsConstraintParam() {
// expected-error@+1 {{'i1' does not satisfy the constraint}}
"testd.dynparams"() : () -> !testd.parametric<i1>
return
}
// -----
//===----------------------------------------------------------------------===//
// Constraint variables
//===----------------------------------------------------------------------===//
func.func @succeededConstraintVars() {
// CHECK: "testd.constraint_vars"() : () -> (i32, i32)
"testd.constraint_vars"() : () -> (i32, i32)
return
}
// -----
func.func @succeededConstraintVars2() {
// CHECK: "testd.constraint_vars"() : () -> (i64, i64)
"testd.constraint_vars"() : () -> (i64, i64)
return
}
// -----
func.func @failedConstraintVars() {
// expected-error@+1 {{expected 'i64' but got 'i32'}}
"testd.constraint_vars"() : () -> (i64, i32)
return
}
// -----
//===----------------------------------------------------------------------===//
// Constraint attributes
//===----------------------------------------------------------------------===//
func.func @succeededAttrs() {
// CHECK: "testd.attrs"() {attr1 = i32, attr2 = i64} : () -> ()
"testd.attrs"() {attr1 = i32, attr2 = i64} : () -> ()
return
}
// -----
func.func @failedAttrsMissingAttr() {
// expected-error@+1 {{attribute "attr2" is expected but not provided}}
"testd.attrs"() {attr1 = i32} : () -> ()
return
}
// -----
func.func @failedAttrsConstraint() {
// expected-error@+1 {{expected 'i32' but got 'i64'}}
"testd.attrs"() {attr1 = i64, attr2 = i64} : () -> ()
return
}
// -----
func.func @failedAttrsConstraint2() {
// expected-error@+1 {{expected 'i64' but got 'i32'}}
"testd.attrs"() {attr1 = i32, attr2 = i32} : () -> ()
return
}
// -----
//===----------------------------------------------------------------------===//
// Regions
//===----------------------------------------------------------------------===//
// CHECK: func.func @succeededRegions
func.func @succeededRegions() {
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
^bb1(%arg0: i32, %arg1: i64):
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1:
llvm.unreachable
}) : () -> ()
return
}
// -----
// CHECK: func.func @succeededRegionWithNoConstraints
func.func @succeededRegionWithNoConstraints() {
"testd.regions"() (
{
^bb1(%arg0: i32, %arg1: i64, %arg2 : f64):
llvm.unreachable
^bb2(%arg3: i32, %arg4: i64, %arg5 : f64):
llvm.unreachable
^bb3(%arg6: i32, %arg7: i64, %arg8 : f64):
llvm.unreachable
^bb4(%arg9: i32, %arg10: i64, %arg11 : f64):
llvm.unreachable
^bb5(%arg12: i32, %arg13: i64, %arg14 : f64):
llvm.unreachable
},
{
^bb1(%arg0: i32, %arg1: i64):
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1:
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @failedRegionArgsLessThanNeeded() {
// expected-note@+1 {{see the operation}}
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
// expected-error@+1 {{expected region 1 to have 2 arguments but got 1}}
^bb1(%arg0: i32):
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1:
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @failedRegionArgsMoreThanNeeded() {
// expected-note@+1 {{see the operation}}
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
// expected-error@+1 {{expected region 1 to have 2 arguments but got 3}}
^bb1(%arg0: i32, %arg1: i64, %arg2 : f64):
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1:
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @failedRegionArgsEmptyButRequired() {
// expected-error@+1 {{expected region 1 to have 2 arguments but got 0}}
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
^bb1():
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1:
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @faIledRegionArgsConstraint() {
// expected-note@+1 {{see the operation}}
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
// expected-error@+1 {{expected 'i64' but got 'f64'}}
^bb1(%arg0: i32, %arg1: f64):
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1:
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @failedRegionBlocksCountLessThanNeeded() {
// expected-error@+1 {{expected region 2 to have 3 block(s) but got 2}}
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
^bb1(%arg0: i32, %arg1: i64):
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1:
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @failedRegionBlocksCountMoreThanNeeded() {
// expected-error@+1 {{expected region 2 to have 3 block(s) but got 4}}
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
^bb1(%arg0: i32, %arg1: i64):
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb4:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1:
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @failedRegionWithEmptyArgs() {
// expected-note@+1 {{see the operation}}
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
^bb1(%arg0: i32, %arg1: i64):
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
// expected-error@+1 {{expected region 3 to have 0 arguments but got 2}}
^bb1(%arg0: i32, %arg1: i64):
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @failedRegionWithLessBlocksThanNeeded() {
// expected-error@+1 {{'testd.regions' op unexpected number of regions: expected 4 but got 3}}
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1:
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @failedRegionWithMoreBlocksThanNeeded() {
// expected-error@+1 {{'testd.regions' op unexpected number of regions: expected 4 but got 5}}
"testd.regions"() (
{
^bb1:
llvm.unreachable
},
{
^bb1(%arg0: i32, %arg1: i64):
llvm.unreachable
},
{
^bb1:
cf.br ^bb3
^bb2:
cf.br ^bb3
^bb3:
llvm.unreachable
},
{
^bb1(%arg0: i32, %arg1: i64):
llvm.unreachable
},
{
^bb1(%arg0: i32, %arg1: i64):
llvm.unreachable
}) : () -> ()
return
}
// -----
func.func @successReuseConstraintBetweenRegionAndOperand() {
%0 = arith.constant 42 : i32
"testd.region_and_operand"(%0) ({
^bb(%1: i32):
llvm.unreachable
}) : (i32) -> ()
return
}
// -----
func.func @failedReuseConstraintBetweenRegionAndOperand() {
%0 = arith.constant 42 : i32
// expected-note@+1 {{see the operation}}
"testd.region_and_operand"(%0) ({
// expected-error@+1 {{expected 'i32' but got 'i64'}}
^bb(%1: i64):
llvm.unreachable
}) : (i32) -> ()
return
}