[Moore] Add `moore.string_cmp` op (#8447)

Add a new op to handle operations involving `!moore.string` operands per 
the rules mentioned in IEEE 1800-2012 table 6-9 "String operators".
This commit is contained in:
Annu Singh 2025-05-01 21:24:38 +05:30 committed by GitHub
parent aa49f0adb8
commit 25b09ba72b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 110 additions and 0 deletions

View File

@ -623,6 +623,19 @@ def UArrayCmpPredicateAttr : I64EnumAttr<
let cppNamespace = "circt::moore";
}
def StringCmpPredicateAttr : I64EnumAttr<
"StringCmpPredicate", "",
[
I64EnumAttrCase<"eq", 0>,
I64EnumAttrCase<"ne", 1>,
I64EnumAttrCase<"lt", 2>,
I64EnumAttrCase<"le", 3>,
I64EnumAttrCase<"gt", 4>,
I64EnumAttrCase<"ge", 5>
]> {
let cppNamespace = "circt::moore";
}
def NegOp : MooreOp<"neg", [Pure, SameOperandsAndResultType]> {
let summary = "Arithmetic negation";
let description = [{
@ -926,6 +939,35 @@ def UArrayCmpOp : MooreOp<"uarray_cmp", [
}];
}
def StringCmpOp : MooreOp<"string_cmp", [
Pure,
SameTypeOperands
]> {
let description = [{
Compares two string operands using the specified
predicate and returns a single bit result. Supported predicates:
- eq : equal
- ne : not equal
- lt : less than
- le : less or equal
- gt : greater than
- ge : greater or equal
The equality operator yields 1 if its operands are equal and 0 otherwise.
Relational operators compare two strings lexicographically,
returning 1 when the specified condition holds and 0 when it does not.
}];
let arguments = (ins
StringCmpPredicateAttr:$predicate,
StringType:$lhs,
StringType:$rhs
);
let results = (outs BitType:$result);
let assemblyFormat = [{
$predicate $lhs `,` $rhs attr-dict `:` type($lhs) `->` type($result)
}];
}
class LogicalEqOpBase<string mnemonic> : MooreOp<mnemonic, [
Pure,
Commutative,

View File

@ -293,12 +293,18 @@ struct RvalueExprVisitor {
if (isa<moore::UnpackedArrayType>(lhs.getType()))
return builder.create<moore::UArrayCmpOp>(
loc, moore::UArrayCmpPredicate::eq, lhs, rhs);
else if (isa<moore::StringType>(lhs.getType()))
return builder.create<moore::StringCmpOp>(
loc, moore::StringCmpPredicate::eq, lhs, rhs);
else
return createBinary<moore::EqOp>(lhs, rhs);
case BinaryOperator::Inequality:
if (isa<moore::UnpackedArrayType>(lhs.getType()))
return builder.create<moore::UArrayCmpOp>(
loc, moore::UArrayCmpPredicate::ne, lhs, rhs);
else if (isa<moore::StringType>(lhs.getType()))
return builder.create<moore::StringCmpOp>(
loc, moore::StringCmpPredicate::ne, lhs, rhs);
else
return createBinary<moore::NeOp>(lhs, rhs);
case BinaryOperator::CaseEquality:
@ -313,21 +319,33 @@ struct RvalueExprVisitor {
case BinaryOperator::GreaterThanEqual:
if (expr.left().type->isSigned())
return createBinary<moore::SgeOp>(lhs, rhs);
else if (isa<moore::StringType>(lhs.getType()))
return builder.create<moore::StringCmpOp>(
loc, moore::StringCmpPredicate::ge, lhs, rhs);
else
return createBinary<moore::UgeOp>(lhs, rhs);
case BinaryOperator::GreaterThan:
if (expr.left().type->isSigned())
return createBinary<moore::SgtOp>(lhs, rhs);
else if (isa<moore::StringType>(lhs.getType()))
return builder.create<moore::StringCmpOp>(
loc, moore::StringCmpPredicate::gt, lhs, rhs);
else
return createBinary<moore::UgtOp>(lhs, rhs);
case BinaryOperator::LessThanEqual:
if (expr.left().type->isSigned())
return createBinary<moore::SleOp>(lhs, rhs);
else if (isa<moore::StringType>(lhs.getType()))
return builder.create<moore::StringCmpOp>(
loc, moore::StringCmpPredicate::le, lhs, rhs);
else
return createBinary<moore::UleOp>(lhs, rhs);
case BinaryOperator::LessThan:
if (expr.left().type->isSigned())
return createBinary<moore::SltOp>(lhs, rhs);
else if (isa<moore::StringType>(lhs.getType()))
return builder.create<moore::StringCmpOp>(
loc, moore::StringCmpPredicate::lt, lhs, rhs);
else
return createBinary<moore::UltOp>(lhs, rhs);

View File

@ -735,6 +735,14 @@ module Expressions;
bit [31:0] arr2 [2];
// CHECK: %m = moore.variable : <l4>
logic [3:0] m;
// CHECK: [[STR_HELLO:%.+]] = moore.string_constant "Hello" : i40
// CHECK: [[CONV_HELLO:%.+]] = moore.conversion [[STR_HELLO]] : !moore.i40 -> !moore.string
// CHECK: [[VAR_S:%.+]] = moore.variable [[CONV_HELLO]] : <string>
string s = "Hello";
// CHECK: [[STR_WORLD:%.+]] = moore.string_constant "World" : i40
// CHECK: [[CONV_WORLD:%.+]] = moore.conversion [[STR_WORLD]] : !moore.i40 -> !moore.string
// CHECK: [[VAR_S1:%.+]] = moore.variable [[CONV_WORLD]] : <string>
string s1 = "World";
initial begin
// CHECK: moore.constant 0 : i32
@ -1169,6 +1177,31 @@ module Expressions;
// CHECK: moore.uarray_cmp ne [[TMP3]], [[TMP4]] : <2 x i32> -> i1
x = arr1 != arr2;
// CHECK: [[TMP5:%.+]] = moore.read %s
// CHECK: [[TMP6:%.+]] = moore.read %s1
// CHECK: moore.string_cmp eq [[TMP5]], [[TMP6]] : string -> i1
x = s == s1;
// CHECK: [[TMP7:%.+]] = moore.read %s
// CHECK: [[TMP8:%.+]] = moore.read %s1
// CHECK: moore.string_cmp ne [[TMP7]], [[TMP8]] : string -> i1
x = s != s1;
// CHECK: [[TMP9:%.+]] = moore.read %s
// CHECK: [[TMP10:%.+]] = moore.read %s1
// CHECK: moore.string_cmp gt [[TMP9]], [[TMP10]] : string -> i1
x = s > s1;
// CHECK: [[TMP11:%.+]] = moore.read %s
// CHECK: [[TMP12:%.+]] = moore.read %s1
// CHECK: moore.string_cmp ge [[TMP11]], [[TMP12]] : string -> i1
x = s >= s1;
// CHECK: [[TMP13:%.+]] = moore.read %s
// CHECK: [[TMP14:%.+]] = moore.read %s1
// CHECK: moore.string_cmp lt [[TMP13]], [[TMP14]] : string -> i1
x = s < s1;
// CHECK: [[TMP15:%.+]] = moore.read %s
// CHECK: [[TMP16:%.+]] = moore.read %s1
// CHECK: moore.string_cmp le [[TMP15]], [[TMP16]] : string -> i1
x = s <= s1;
// CHECK: [[TMP1:%.+]] = moore.read %a
// CHECK: [[TMP2:%.+]] = moore.read %b
// CHECK: moore.ne [[TMP1]], [[TMP2]] : i32 -> i1

View File

@ -122,6 +122,11 @@ moore.module @Expressions(
// CHECK-SAME: in [[ARRAY2:%[^:]+]] : !moore.uarray<2 x uarray<4 x i8>>
in %array2: !moore.uarray<2 x uarray<4 x i8>>,
// CHECK-SAME: in %s1 : !moore.string
in %s1 : !moore.string,
// CHECK-SAME: in %s2 : !moore.string
in %s2 : !moore.string,
// CHECK-SAME: in [[REF_A:%[^:]+]] : !moore.ref<i32>
in %refA: !moore.ref<i32>,
// CHECK-SAME: in [[REF_B:%[^:]+]] : !moore.ref<i32>
@ -310,6 +315,18 @@ moore.module @Expressions(
moore.string_constant "Test" : i128
// CHECK: moore.string_constant "" : i128
moore.string_constant "" : i128
// CHECK: moore.string_cmp eq %s1, %s2 : string -> i1
moore.string_cmp eq %s1, %s2 : string -> i1
// CHECK: moore.string_cmp ne %s1, %s2 : string -> i1
moore.string_cmp ne %s1, %s2 : string -> i1
// CHECK: moore.string_cmp lt %s1, %s2 : string -> i1
moore.string_cmp lt %s1, %s2 : string -> i1
// CHECK: moore.string_cmp le %s1, %s2 : string -> i1
moore.string_cmp le %s1, %s2 : string -> i1
// CHECK: moore.string_cmp gt %s1, %s2 : string -> i1
moore.string_cmp gt %s1, %s2 : string -> i1
// CHECK: moore.string_cmp ge %s1, %s2 : string -> i1
moore.string_cmp ge %s1, %s2 : string -> i1
moore.output
}