Skip to content

Commit dd8e443

Browse files
committed
[mlir][CAPI] Add a simple MlirOpOperand API for MlirValue uses.
This allows basic IR traversal via the C API, which is useful for analyses in languages other than C++. This starts by defining an MlirOpOperand struct to encapsulate a pair of an owner operation and an operand number. A new API is added for MlirValue, to return the first use of the Value as an MlirOpOperand, or a "null" MlirOpOperand if there are no uses. A couple APIs are added for MlirOpOperand. The first checks if an MlirOpOperand is "null", by checking if its owner's pointer is null. The second supports iteration along the use-def lists by accepting an MlirOpOperand and returning the next use of the Value as another MlirOpOperand, or a "null" MlirOpOperand if there are no more uses. Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D139596
1 parent 9beb8d1 commit dd8e443

File tree

4 files changed

+94
-4
lines changed

4 files changed

+94
-4
lines changed

mlir/include/mlir-c/IR.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ DEFINE_C_API_STRUCT(MlirContext, void);
5252
DEFINE_C_API_STRUCT(MlirDialect, void);
5353
DEFINE_C_API_STRUCT(MlirDialectRegistry, void);
5454
DEFINE_C_API_STRUCT(MlirOperation, void);
55+
DEFINE_C_API_STRUCT(MlirOpOperand, void);
5556
DEFINE_C_API_STRUCT(MlirOpPrintingFlags, void);
5657
DEFINE_C_API_STRUCT(MlirBlock, void);
5758
DEFINE_C_API_STRUCT(MlirRegion, void);
@@ -728,6 +729,29 @@ MLIR_CAPI_EXPORTED void mlirValueDump(MlirValue value);
728729
MLIR_CAPI_EXPORTED void
729730
mlirValuePrint(MlirValue value, MlirStringCallback callback, void *userData);
730731

732+
/// Returns an op operand representing the first use of the value, or a null op
733+
/// operand if there are no uses.
734+
MLIR_CAPI_EXPORTED MlirOpOperand mlirValueGetFirstUse(MlirValue value);
735+
736+
//===----------------------------------------------------------------------===//
737+
// OpOperand API.
738+
//===----------------------------------------------------------------------===//
739+
740+
/// Returns whether the op operand is null.
741+
MLIR_CAPI_EXPORTED bool mlirOpOperandIsNull(MlirOpOperand opOperand);
742+
743+
/// Returns the owner operation of an op operand.
744+
MLIR_CAPI_EXPORTED MlirOperation mlirOpOperandGetOwner(MlirOpOperand opOperand);
745+
746+
/// Returns the operand number of an op operand.
747+
MLIR_CAPI_EXPORTED unsigned
748+
mlirOpOperandGetOperandNumber(MlirOpOperand opOperand);
749+
750+
/// Returns an op operand representing the next use of the value, or a null op
751+
/// operand if there is no next use.
752+
MLIR_CAPI_EXPORTED MlirOpOperand
753+
mlirOpOperandGetNextUse(MlirOpOperand opOperand);
754+
731755
//===----------------------------------------------------------------------===//
732756
// Type API.
733757
//===----------------------------------------------------------------------===//

mlir/include/mlir/CAPI/IR.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ DEFINE_C_API_PTR_METHODS(MlirDialect, mlir::Dialect)
2525
DEFINE_C_API_PTR_METHODS(MlirDialectRegistry, mlir::DialectRegistry)
2626
DEFINE_C_API_PTR_METHODS(MlirOperation, mlir::Operation)
2727
DEFINE_C_API_PTR_METHODS(MlirBlock, mlir::Block)
28+
DEFINE_C_API_PTR_METHODS(MlirOpOperand, mlir::OpOperand)
2829
DEFINE_C_API_PTR_METHODS(MlirOpPrintingFlags, mlir::OpPrintingFlags)
2930
DEFINE_C_API_PTR_METHODS(MlirRegion, mlir::Region)
3031
DEFINE_C_API_PTR_METHODS(MlirSymbolTable, mlir::SymbolTable)

mlir/lib/CAPI/IR/IR.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,43 @@ void mlirValuePrint(MlirValue value, MlirStringCallback callback,
719719
unwrap(value).print(stream);
720720
}
721721

722+
MlirOpOperand mlirValueGetFirstUse(MlirValue value) {
723+
Value cppValue = unwrap(value);
724+
if (cppValue.use_empty())
725+
return {};
726+
727+
OpOperand *opOperand = cppValue.use_begin().getOperand();
728+
729+
return wrap(opOperand);
730+
}
731+
732+
//===----------------------------------------------------------------------===//
733+
// OpOperand API.
734+
//===----------------------------------------------------------------------===//
735+
736+
bool mlirOpOperandIsNull(MlirOpOperand opOperand) { return !opOperand.ptr; }
737+
738+
MlirOperation mlirOpOperandGetOwner(MlirOpOperand opOperand) {
739+
return wrap(unwrap(opOperand)->getOwner());
740+
}
741+
742+
unsigned mlirOpOperandGetOperandNumber(MlirOpOperand opOperand) {
743+
return unwrap(opOperand)->getOperandNumber();
744+
}
745+
746+
MlirOpOperand mlirOpOperandGetNextUse(MlirOpOperand opOperand) {
747+
if (mlirOpOperandIsNull(opOperand))
748+
return {};
749+
750+
OpOperand *nextOpOperand = static_cast<OpOperand *>(
751+
unwrap(opOperand)->getNextOperandUsingThisValue());
752+
753+
if (!nextOpOperand)
754+
return {};
755+
756+
return wrap(nextOpOperand);
757+
}
758+
722759
//===----------------------------------------------------------------------===//
723760
// Type API.
724761
//===----------------------------------------------------------------------===//

mlir/test/CAPI/ir.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,17 +1758,45 @@ int testOperands(void) {
17581758
fprintf(stderr, "Num Operands: %" PRIdPTR "\n", numOperands);
17591759
// CHECK: Num Operands: 1
17601760

1761-
MlirValue opOperand = mlirOperationGetOperand(op, 0);
1761+
MlirValue opOperand1 = mlirOperationGetOperand(op, 0);
17621762
fprintf(stderr, "Original operand: ");
1763-
mlirValuePrint(opOperand, printToStderr, NULL);
1763+
mlirValuePrint(opOperand1, printToStderr, NULL);
17641764
// CHECK: Original operand: {{.+}} arith.constant 0 : index
17651765

17661766
mlirOperationSetOperand(op, 0, constOneValue);
1767-
opOperand = mlirOperationGetOperand(op, 0);
1767+
MlirValue opOperand2 = mlirOperationGetOperand(op, 0);
17681768
fprintf(stderr, "Updated operand: ");
1769-
mlirValuePrint(opOperand, printToStderr, NULL);
1769+
mlirValuePrint(opOperand2, printToStderr, NULL);
17701770
// CHECK: Updated operand: {{.+}} arith.constant 1 : index
17711771

1772+
// Test op operand APIs.
1773+
MlirOpOperand use1 = mlirValueGetFirstUse(opOperand1);
1774+
if (!mlirOpOperandIsNull(use1)) {
1775+
fprintf(stderr, "ERROR: Use should be null\n");
1776+
return 1;
1777+
}
1778+
1779+
MlirOpOperand use2 = mlirValueGetFirstUse(opOperand2);
1780+
if (mlirOpOperandIsNull(use2)) {
1781+
fprintf(stderr, "ERROR: Use should not be null\n");
1782+
return 2;
1783+
}
1784+
1785+
fprintf(stderr, "Use owner: ");
1786+
mlirOperationPrint(mlirOpOperandGetOwner(use2), printToStderr, NULL);
1787+
fprintf(stderr, "\n");
1788+
// CHECK: Use owner: "dummy.op"
1789+
1790+
fprintf(stderr, "Use operandNumber: %d\n",
1791+
mlirOpOperandGetOperandNumber(use2));
1792+
// CHECK: Use operandNumber: 0
1793+
1794+
use2 = mlirOpOperandGetNextUse(use2);
1795+
if (!mlirOpOperandIsNull(use2)) {
1796+
fprintf(stderr, "ERROR: Next use should be null\n");
1797+
return 3;
1798+
}
1799+
17721800
mlirOperationDestroy(op);
17731801
mlirOperationDestroy(constZero);
17741802
mlirOperationDestroy(constOne);

0 commit comments

Comments
 (0)