[RTGTest] Add representation for immediates (#8053)

This commit is contained in:
Martin Erhart 2025-01-31 09:57:17 +00:00 committed by GitHub
parent c4e458f6d9
commit a4fa04d143
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 327 additions and 0 deletions

View File

@ -31,6 +31,27 @@ MLIR_CAPI_EXPORTED bool rtgtestTypeIsACPU(MlirType type);
/// Creates an RTGTest CPU type in the context.
MLIR_CAPI_EXPORTED MlirType rtgtestCPUTypeGet(MlirContext ctxt);
// Immediates.
//===----------------------------------------------------------------------===//
/// If the type is an RTGTest Imm12Type.
MLIR_CAPI_EXPORTED bool rtgtestTypeIsAImm12(MlirType type);
/// Creates an RTGTest Imm12 type in the context.
MLIR_CAPI_EXPORTED MlirType rtgtestImm12TypeGet(MlirContext ctxt);
/// If the type is an RTGTest Imm21Type.
MLIR_CAPI_EXPORTED bool rtgtestTypeIsAImm21(MlirType type);
/// Creates an RTGTest Imm21 type in the context.
MLIR_CAPI_EXPORTED MlirType rtgtestImm21TypeGet(MlirContext ctxt);
/// If the type is an RTGTest Imm32Type.
MLIR_CAPI_EXPORTED bool rtgtestTypeIsAImm32(MlirType type);
/// Creates an RTGTest Imm32 type in the context.
MLIR_CAPI_EXPORTED MlirType rtgtestImm32TypeGet(MlirContext ctxt);
//===----------------------------------------------------------------------===//
// Attribute API.
//===----------------------------------------------------------------------===//
@ -240,6 +261,39 @@ MLIR_CAPI_EXPORTED bool rtgtestAttrIsARegT6(MlirAttribute attr);
/// Creates an RTGTest RegT6 attribute in the context.
MLIR_CAPI_EXPORTED MlirAttribute rtgtestRegT6AttrGet(MlirContext ctxt);
// Immediates.
//===----------------------------------------------------------------------===//
/// If the attribute is an RTGTest Imm12Attr.
MLIR_CAPI_EXPORTED bool rtgtestAttrIsAImm12(MlirAttribute attr);
/// Creates an RTGTest Imm12 attribute in the context.
MLIR_CAPI_EXPORTED MlirAttribute rtgtestImm12AttrGet(MlirContext ctxt,
unsigned value);
/// Returns the value represented by the Imm12 attribute.
MLIR_CAPI_EXPORTED unsigned rtgtestImm12AttrGetValue(MlirAttribute attr);
/// If the attribute is an RTGTest Imm21Attr.
MLIR_CAPI_EXPORTED bool rtgtestAttrIsAImm21(MlirAttribute attr);
/// Creates an RTGTest Imm21 attribute in the context.
MLIR_CAPI_EXPORTED MlirAttribute rtgtestImm21AttrGet(MlirContext ctxt,
unsigned value);
/// Returns the value represented by the Imm21 attribute.
MLIR_CAPI_EXPORTED unsigned rtgtestImm21AttrGetValue(MlirAttribute attr);
/// If the attribute is an RTGTest Imm32Attr.
MLIR_CAPI_EXPORTED bool rtgtestAttrIsAImm32(MlirAttribute attr);
/// Creates an RTGTest Imm32 attribute in the context.
MLIR_CAPI_EXPORTED MlirAttribute rtgtestImm32AttrGet(MlirContext ctxt,
unsigned value);
/// Returns the value represented by the Imm32 attribute.
MLIR_CAPI_EXPORTED unsigned rtgtestImm32AttrGetValue(MlirAttribute attr);
#ifdef __cplusplus
}
#endif

View File

@ -35,6 +35,40 @@ def CPUAttr : RTGTestAttrDef<"CPU", [ContextResourceAttrInterface]> {
}];
}
class ImmediateAttrBase<int width> : RTGTestAttrDef<"Imm" # width, [
DeclareAttrInterfaceMethods<TypedAttrInterface>,
]> {
let summary = "represents a " # width # "-bit immediate value";
let mnemonic = "imm" # width;
let parameters = (ins "uint32_t":$value);
let assemblyFormat = "`<` $value `>`";
let extraClassDefinition = [{
Type $cppClass::getType() const {
return Imm}] # width # [{Type::get(getContext());
}
LogicalResult $cppClass::verify(
::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
uint32_t value) {
if (32 - llvm::countl_zero(value) > }] # width # [{)
return emitError() << "cannot represent " << value << " with }] #
width # [{ bits";
return success();
}
}];
let genVerifyDecl = 1;
}
def Imm12 : ImmediateAttrBase<12>;
def Imm21 : ImmediateAttrBase<21>;
def Imm32 : ImmediateAttrBase<32>;
class IntegerRegisterAttrBase<string cppName, string name, int classIndex>
: RTGTestAttrDef<cppName, [RegisterAttrInterface]> {

View File

@ -39,6 +39,21 @@ def CPUDeclOp : RTGTestOp<"cpu_decl", [
let hasFolder = 1;
}
def ImmediateOp : RTGTestOp<"immediate", [
Pure,
ConstantLike,
FirstAttrDerivedResultType,
DeclareOpInterfaceMethods<InferTypeOpInterface>,
]> {
let summary = "declare an immediate value";
let arguments = (ins AnyAttrOf<[Imm12, Imm21, Imm32]>:$imm);
let results = (outs AnyType:$result);
let assemblyFormat = "$imm attr-dict";
let hasFolder = 1;
}
def ConstantTestOp : RTGTestOp<"constant_test", [
Pure, ConstantLike,
]> {

View File

@ -33,6 +33,15 @@ def CPUType : RTGTestTypeDef<"CPU", [ContextResourceTypeInterface]> {
let assemblyFormat = "";
}
class ImmTypeBase<int width> : TypeDef<RTGTestDialect, "Imm" # width, []> {
let summary = "represents a " # width # "-bit immediate";
let mnemonic = "imm" # width;
}
def Imm12Type : ImmTypeBase<12>;
def Imm21Type : ImmTypeBase<21>;
def Imm32Type : ImmTypeBase<32>;
def IntegerRegisterType : TypeDef<RTGTestDialect, "IntegerRegister", [
RegisterTypeInterface
]> {

View File

@ -165,3 +165,16 @@ with Context() as ctx, Location.unknown():
rtg.FixedRegisterOp(rtgtest.RegT6Attr.get())
print(m)
with Context() as ctx, Location.unknown():
circt.register_dialects(ctx)
m = Module.create()
with InsertionPoint(m.body):
# CHECK: rtgtest.immediate #rtgtest.imm12<3> : !rtgtest.imm12
rtgtest.ImmediateOp(rtgtest.Imm12Attr.get(3))
# CHECK: rtgtest.immediate #rtgtest.imm21<3> : !rtgtest.imm21
rtgtest.ImmediateOp(rtgtest.Imm21Attr.get(3))
# CHECK: rtgtest.immediate #rtgtest.imm32<3> : !rtgtest.imm32
rtgtest.ImmediateOp(rtgtest.Imm32Attr.get(3))
print(m)

View File

@ -30,6 +30,30 @@ void circt::python::populateDialectRTGTestSubmodule(nb::module_ &m) {
},
nb::arg("self"), nb::arg("ctxt") = nullptr);
mlir_type_subclass(m, "Imm12Type", rtgtestTypeIsAImm12)
.def_classmethod(
"get",
[](nb::object cls, MlirContext ctxt) {
return cls(rtgtestImm12TypeGet(ctxt));
},
nb::arg("self"), nb::arg("ctxt") = nullptr);
mlir_type_subclass(m, "Imm21Type", rtgtestTypeIsAImm21)
.def_classmethod(
"get",
[](nb::object cls, MlirContext ctxt) {
return cls(rtgtestImm21TypeGet(ctxt));
},
nb::arg("self"), nb::arg("ctxt") = nullptr);
mlir_type_subclass(m, "Imm32Type", rtgtestTypeIsAImm32)
.def_classmethod(
"get",
[](nb::object cls, MlirContext ctxt) {
return cls(rtgtestImm32TypeGet(ctxt));
},
nb::arg("self"), nb::arg("ctxt") = nullptr);
mlir_attribute_subclass(m, "CPUAttr", rtgtestAttrIsACPU)
.def_classmethod(
"get",
@ -295,4 +319,37 @@ void circt::python::populateDialectRTGTestSubmodule(nb::module_ &m) {
return cls(rtgtestRegT6AttrGet(ctxt));
},
nb::arg("self"), nb::arg("ctxt") = nullptr);
mlir_attribute_subclass(m, "Imm12Attr", rtgtestAttrIsAImm12)
.def_classmethod(
"get",
[](nb::object cls, unsigned value, MlirContext ctxt) {
return cls(rtgtestImm12AttrGet(ctxt, value));
},
nb::arg("self"), nb::arg("value"), nb::arg("ctxt") = nullptr)
.def_property_readonly("value", [](MlirAttribute self) {
return rtgtestImm12AttrGetValue(self);
});
mlir_attribute_subclass(m, "Imm21Attr", rtgtestAttrIsAImm21)
.def_classmethod(
"get",
[](nb::object cls, unsigned value, MlirContext ctxt) {
return cls(rtgtestImm21AttrGet(ctxt, value));
},
nb::arg("self"), nb::arg("value"), nb::arg("ctxt") = nullptr)
.def_property_readonly("value", [](MlirAttribute self) {
return rtgtestImm21AttrGetValue(self);
});
mlir_attribute_subclass(m, "Imm32Attr", rtgtestAttrIsAImm32)
.def_classmethod(
"get",
[](nb::object cls, unsigned value, MlirContext ctxt) {
return cls(rtgtestImm32AttrGet(ctxt, value));
},
nb::arg("self"), nb::arg("value"), nb::arg("ctxt") = nullptr)
.def_property_readonly("value", [](MlirAttribute self) {
return rtgtestImm32AttrGetValue(self);
});
}

View File

@ -32,6 +32,27 @@ MlirType rtgtestCPUTypeGet(MlirContext ctxt) {
return wrap(CPUType::get(unwrap(ctxt)));
}
// Immediates.
//===----------------------------------------------------------------------===//
bool rtgtestTypeIsAImm12(MlirType type) { return isa<Imm12Type>(unwrap(type)); }
MlirType rtgtestImm12TypeGet(MlirContext ctxt) {
return wrap(Imm12Type::get(unwrap(ctxt)));
}
bool rtgtestTypeIsAImm21(MlirType type) { return isa<Imm21Type>(unwrap(type)); }
MlirType rtgtestImm21TypeGet(MlirContext ctxt) {
return wrap(Imm21Type::get(unwrap(ctxt)));
}
bool rtgtestTypeIsAImm32(MlirType type) { return isa<Imm32Type>(unwrap(type)); }
MlirType rtgtestImm32TypeGet(MlirContext ctxt) {
return wrap(Imm32Type::get(unwrap(ctxt)));
}
//===----------------------------------------------------------------------===//
// Attribute API.
//===----------------------------------------------------------------------===//
@ -306,3 +327,42 @@ bool rtgtestAttrIsARegT6(MlirAttribute attr) {
MlirAttribute rtgtestRegT6AttrGet(MlirContext ctxt) {
return wrap(RegT6Attr::get(unwrap(ctxt)));
}
// Immediates.
//===----------------------------------------------------------------------===//
bool rtgtestAttrIsAImm12(MlirAttribute attr) {
return isa<Imm12Attr>(unwrap(attr));
}
MlirAttribute rtgtestImm12AttrGet(MlirContext ctxt, unsigned value) {
return wrap(Imm12Attr::get(unwrap(ctxt), value));
}
unsigned rtgtestImm12AttrGetValue(MlirAttribute attr) {
return cast<Imm12Attr>(unwrap(attr)).getValue();
}
bool rtgtestAttrIsAImm21(MlirAttribute attr) {
return isa<Imm21Attr>(unwrap(attr));
}
MlirAttribute rtgtestImm21AttrGet(MlirContext ctxt, unsigned value) {
return wrap(Imm21Attr::get(unwrap(ctxt), value));
}
unsigned rtgtestImm21AttrGetValue(MlirAttribute attr) {
return cast<Imm21Attr>(unwrap(attr)).getValue();
}
bool rtgtestAttrIsAImm32(MlirAttribute attr) {
return isa<Imm32Attr>(unwrap(attr));
}
MlirAttribute rtgtestImm32AttrGet(MlirContext ctxt, unsigned value) {
return wrap(Imm32Attr::get(unwrap(ctxt), value));
}
unsigned rtgtestImm32AttrGetValue(MlirAttribute attr) {
return cast<Imm32Attr>(unwrap(attr)).getValue();
}

View File

@ -25,6 +25,23 @@ size_t CPUDeclOp::getIdentifier(size_t idx) { return getId().getId(); }
mlir::OpFoldResult CPUDeclOp::fold(FoldAdaptor adaptor) { return getId(); }
//===----------------------------------------------------------------------===//
// ImmediateOp
//===----------------------------------------------------------------------===//
mlir::OpFoldResult ImmediateOp::fold(FoldAdaptor adaptor) {
return getImmAttr();
}
LogicalResult ImmediateOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> loc, ValueRange operands,
DictionaryAttr attributes, OpaqueProperties properties,
mlir::RegionRange regions, SmallVectorImpl<Type> &inferredReturnTypes) {
inferredReturnTypes.push_back(
cast<TypedAttr>(properties.as<Properties *>()->getImm()).getType());
return success();
}
//===----------------------------------------------------------------------===//
// ConstantTestOp
//===----------------------------------------------------------------------===//

View File

@ -260,6 +260,56 @@ static void testRegisters(MlirContext ctx) {
}
}
static void testImmediates(MlirContext ctx) {
MlirType imm12Type = rtgtestImm12TypeGet(ctx);
// CHECK: is_imm12
fprintf(stderr,
rtgtestTypeIsAImm12(imm12Type) ? "is_imm12\n" : "isnot_imm12\n");
// CHECK: !rtgtest.imm12
mlirTypeDump(imm12Type);
MlirType imm21Type = rtgtestImm21TypeGet(ctx);
// CHECK: is_imm21
fprintf(stderr,
rtgtestTypeIsAImm21(imm21Type) ? "is_imm21\n" : "isnot_imm21\n");
// CHECK: !rtgtest.imm21
mlirTypeDump(imm21Type);
MlirType imm32Type = rtgtestImm32TypeGet(ctx);
// CHECK: is_imm32
fprintf(stderr,
rtgtestTypeIsAImm32(imm32Type) ? "is_imm32\n" : "isnot_imm32\n");
// CHECK: !rtgtest.imm32
mlirTypeDump(imm32Type);
MlirAttribute imm12Attr = rtgtestImm12AttrGet(ctx, 3);
// CHECK: is_imm12
fprintf(stderr,
rtgtestAttrIsAImm12(imm12Attr) ? "is_imm12\n" : "isnot_imm12\n");
// CHECK: 3
fprintf(stderr, "%u\n", rtgtestImm12AttrGetValue(imm12Attr));
// CHECK: #rtgtest.imm12<3>
mlirAttributeDump(imm12Attr);
MlirAttribute imm21Attr = rtgtestImm21AttrGet(ctx, 3);
// CHECK: is_imm21
fprintf(stderr,
rtgtestAttrIsAImm21(imm21Attr) ? "is_imm21\n" : "isnot_imm21\n");
// CHECK: 3
fprintf(stderr, "%u\n", rtgtestImm21AttrGetValue(imm21Attr));
// CHECK: #rtgtest.imm21<3>
mlirAttributeDump(imm21Attr);
MlirAttribute imm32Attr = rtgtestImm32AttrGet(ctx, 3);
// CHECK: is_imm32
fprintf(stderr,
rtgtestAttrIsAImm32(imm32Attr) ? "is_imm32\n" : "isnot_imm32\n");
// CHECK: 3
fprintf(stderr, "%u\n", rtgtestImm32AttrGetValue(imm32Attr));
// CHECK: #rtgtest.imm32<3>
mlirAttributeDump(imm32Attr);
}
int main(int argc, char **argv) {
MlirContext ctx = mlirContextCreate();
mlirDialectHandleLoadDialect(mlirGetDialectHandle__rtgtest__(), ctx);
@ -267,6 +317,7 @@ int main(int argc, char **argv) {
testCPUType(ctx);
testCPUAttr(ctx);
testRegisters(ctx);
testImmediates(ctx);
mlirContextDestroy(ctx);

View File

@ -86,6 +86,23 @@ rtg.test @registers : !rtg.dict<reg: !rtgtest.ireg> {
rtg.virtual_reg [#rtgtest.ra, #rtgtest.sp]
}
// CHECK-LABEL: @immediates
rtg.test @immediates : !rtg.dict<> {
// CHECK: rtgtest.immediate #rtgtest.imm12<3> : !rtgtest.imm12
rtgtest.immediate #rtgtest.imm12<3> : !rtgtest.imm12
// CHECK: rtgtest.immediate #rtgtest.imm21<3> : !rtgtest.imm21
rtgtest.immediate #rtgtest.imm21<3> : !rtgtest.imm21
// CHECK: rtgtest.immediate #rtgtest.imm32<3> : !rtgtest.imm32
rtgtest.immediate #rtgtest.imm32<3> : !rtgtest.imm32
}
// -----
rtg.test @immediateTooBig : !rtg.dict<> {
// expected-error @below {{cannot represent 2000000 with 12 bits}}
rtgtest.immediate #rtgtest.imm12<2000000> : !rtgtest.imm12
}
// -----
rtg.test @emptyAllowed : !rtg.dict<> {