1 //===- ir.c - Simple test of C APIs ---------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 4 // Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 /* RUN: mlir-capi-ir-test 2>&1 | FileCheck %s 11 */ 12 13 #include "mlir-c/IR.h" 14 #include "mlir-c/AffineExpr.h" 15 #include "mlir-c/AffineMap.h" 16 #include "mlir-c/BuiltinAttributes.h" 17 #include "mlir-c/BuiltinTypes.h" 18 #include "mlir-c/Diagnostics.h" 19 #include "mlir-c/Dialect/Func.h" 20 #include "mlir-c/IntegerSet.h" 21 #include "mlir-c/Registration.h" 22 #include "mlir-c/Support.h" 23 24 #include <assert.h> 25 #include <inttypes.h> 26 #include <math.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 void populateLoopBody(MlirContext ctx, MlirBlock loopBody, 32 MlirLocation location, MlirBlock funcBody) { 33 MlirValue iv = mlirBlockGetArgument(loopBody, 0); 34 MlirValue funcArg0 = mlirBlockGetArgument(funcBody, 0); 35 MlirValue funcArg1 = mlirBlockGetArgument(funcBody, 1); 36 MlirType f32Type = 37 mlirTypeParseGet(ctx, mlirStringRefCreateFromCString("f32")); 38 39 MlirOperationState loadLHSState = mlirOperationStateGet( 40 mlirStringRefCreateFromCString("memref.load"), location); 41 MlirValue loadLHSOperands[] = {funcArg0, iv}; 42 mlirOperationStateAddOperands(&loadLHSState, 2, loadLHSOperands); 43 mlirOperationStateAddResults(&loadLHSState, 1, &f32Type); 44 MlirOperation loadLHS = mlirOperationCreate(&loadLHSState); 45 mlirBlockAppendOwnedOperation(loopBody, loadLHS); 46 47 MlirOperationState loadRHSState = mlirOperationStateGet( 48 mlirStringRefCreateFromCString("memref.load"), location); 49 MlirValue loadRHSOperands[] = {funcArg1, iv}; 50 mlirOperationStateAddOperands(&loadRHSState, 2, loadRHSOperands); 51 mlirOperationStateAddResults(&loadRHSState, 1, &f32Type); 52 MlirOperation loadRHS = mlirOperationCreate(&loadRHSState); 53 mlirBlockAppendOwnedOperation(loopBody, loadRHS); 54 55 MlirOperationState addState = mlirOperationStateGet( 56 mlirStringRefCreateFromCString("arith.addf"), location); 57 MlirValue addOperands[] = {mlirOperationGetResult(loadLHS, 0), 58 mlirOperationGetResult(loadRHS, 0)}; 59 mlirOperationStateAddOperands(&addState, 2, addOperands); 60 mlirOperationStateAddResults(&addState, 1, &f32Type); 61 MlirOperation add = mlirOperationCreate(&addState); 62 mlirBlockAppendOwnedOperation(loopBody, add); 63 64 MlirOperationState storeState = mlirOperationStateGet( 65 mlirStringRefCreateFromCString("memref.store"), location); 66 MlirValue storeOperands[] = {mlirOperationGetResult(add, 0), funcArg0, iv}; 67 mlirOperationStateAddOperands(&storeState, 3, storeOperands); 68 MlirOperation store = mlirOperationCreate(&storeState); 69 mlirBlockAppendOwnedOperation(loopBody, store); 70 71 MlirOperationState yieldState = mlirOperationStateGet( 72 mlirStringRefCreateFromCString("scf.yield"), location); 73 MlirOperation yield = mlirOperationCreate(&yieldState); 74 mlirBlockAppendOwnedOperation(loopBody, yield); 75 } 76 77 MlirModule makeAndDumpAdd(MlirContext ctx, MlirLocation location) { 78 MlirModule moduleOp = mlirModuleCreateEmpty(location); 79 MlirBlock moduleBody = mlirModuleGetBody(moduleOp); 80 81 MlirType memrefType = 82 mlirTypeParseGet(ctx, mlirStringRefCreateFromCString("memref<?xf32>")); 83 MlirType funcBodyArgTypes[] = {memrefType, memrefType}; 84 MlirLocation funcBodyArgLocs[] = {location, location}; 85 MlirRegion funcBodyRegion = mlirRegionCreate(); 86 MlirBlock funcBody = 87 mlirBlockCreate(sizeof(funcBodyArgTypes) / sizeof(MlirType), 88 funcBodyArgTypes, funcBodyArgLocs); 89 mlirRegionAppendOwnedBlock(funcBodyRegion, funcBody); 90 91 MlirAttribute funcTypeAttr = mlirAttributeParseGet( 92 ctx, 93 mlirStringRefCreateFromCString("(memref<?xf32>, memref<?xf32>) -> ()")); 94 MlirAttribute funcNameAttr = 95 mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("\"add\"")); 96 MlirNamedAttribute funcAttrs[] = { 97 mlirNamedAttributeGet( 98 mlirIdentifierGet(ctx, 99 mlirStringRefCreateFromCString("function_type")), 100 funcTypeAttr), 101 mlirNamedAttributeGet( 102 mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("sym_name")), 103 funcNameAttr)}; 104 MlirOperationState funcState = mlirOperationStateGet( 105 mlirStringRefCreateFromCString("func.func"), location); 106 mlirOperationStateAddAttributes(&funcState, 2, funcAttrs); 107 mlirOperationStateAddOwnedRegions(&funcState, 1, &funcBodyRegion); 108 MlirOperation func = mlirOperationCreate(&funcState); 109 mlirBlockInsertOwnedOperation(moduleBody, 0, func); 110 111 MlirType indexType = 112 mlirTypeParseGet(ctx, mlirStringRefCreateFromCString("index")); 113 MlirAttribute indexZeroLiteral = 114 mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index")); 115 MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet( 116 mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")), 117 indexZeroLiteral); 118 MlirOperationState constZeroState = mlirOperationStateGet( 119 mlirStringRefCreateFromCString("arith.constant"), location); 120 mlirOperationStateAddResults(&constZeroState, 1, &indexType); 121 mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr); 122 MlirOperation constZero = mlirOperationCreate(&constZeroState); 123 mlirBlockAppendOwnedOperation(funcBody, constZero); 124 125 MlirValue funcArg0 = mlirBlockGetArgument(funcBody, 0); 126 MlirValue constZeroValue = mlirOperationGetResult(constZero, 0); 127 MlirValue dimOperands[] = {funcArg0, constZeroValue}; 128 MlirOperationState dimState = mlirOperationStateGet( 129 mlirStringRefCreateFromCString("memref.dim"), location); 130 mlirOperationStateAddOperands(&dimState, 2, dimOperands); 131 mlirOperationStateAddResults(&dimState, 1, &indexType); 132 MlirOperation dim = mlirOperationCreate(&dimState); 133 mlirBlockAppendOwnedOperation(funcBody, dim); 134 135 MlirRegion loopBodyRegion = mlirRegionCreate(); 136 MlirBlock loopBody = mlirBlockCreate(0, NULL, NULL); 137 mlirBlockAddArgument(loopBody, indexType, location); 138 mlirRegionAppendOwnedBlock(loopBodyRegion, loopBody); 139 140 MlirAttribute indexOneLiteral = 141 mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("1 : index")); 142 MlirNamedAttribute indexOneValueAttr = mlirNamedAttributeGet( 143 mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")), 144 indexOneLiteral); 145 MlirOperationState constOneState = mlirOperationStateGet( 146 mlirStringRefCreateFromCString("arith.constant"), location); 147 mlirOperationStateAddResults(&constOneState, 1, &indexType); 148 mlirOperationStateAddAttributes(&constOneState, 1, &indexOneValueAttr); 149 MlirOperation constOne = mlirOperationCreate(&constOneState); 150 mlirBlockAppendOwnedOperation(funcBody, constOne); 151 152 MlirValue dimValue = mlirOperationGetResult(dim, 0); 153 MlirValue constOneValue = mlirOperationGetResult(constOne, 0); 154 MlirValue loopOperands[] = {constZeroValue, dimValue, constOneValue}; 155 MlirOperationState loopState = mlirOperationStateGet( 156 mlirStringRefCreateFromCString("scf.for"), location); 157 mlirOperationStateAddOperands(&loopState, 3, loopOperands); 158 mlirOperationStateAddOwnedRegions(&loopState, 1, &loopBodyRegion); 159 MlirOperation loop = mlirOperationCreate(&loopState); 160 mlirBlockAppendOwnedOperation(funcBody, loop); 161 162 populateLoopBody(ctx, loopBody, location, funcBody); 163 164 MlirOperationState retState = mlirOperationStateGet( 165 mlirStringRefCreateFromCString("func.return"), location); 166 MlirOperation ret = mlirOperationCreate(&retState); 167 mlirBlockAppendOwnedOperation(funcBody, ret); 168 169 MlirOperation module = mlirModuleGetOperation(moduleOp); 170 mlirOperationDump(module); 171 // clang-format off 172 // CHECK: module { 173 // CHECK: func @add(%[[ARG0:.*]]: memref<?xf32>, %[[ARG1:.*]]: memref<?xf32>) { 174 // CHECK: %[[C0:.*]] = arith.constant 0 : index 175 // CHECK: %[[DIM:.*]] = memref.dim %[[ARG0]], %[[C0]] : memref<?xf32> 176 // CHECK: %[[C1:.*]] = arith.constant 1 : index 177 // CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[DIM]] step %[[C1]] { 178 // CHECK: %[[LHS:.*]] = memref.load %[[ARG0]][%[[I]]] : memref<?xf32> 179 // CHECK: %[[RHS:.*]] = memref.load %[[ARG1]][%[[I]]] : memref<?xf32> 180 // CHECK: %[[SUM:.*]] = arith.addf %[[LHS]], %[[RHS]] : f32 181 // CHECK: memref.store %[[SUM]], %[[ARG0]][%[[I]]] : memref<?xf32> 182 // CHECK: } 183 // CHECK: return 184 // CHECK: } 185 // CHECK: } 186 // clang-format on 187 188 return moduleOp; 189 } 190 191 struct OpListNode { 192 MlirOperation op; 193 struct OpListNode *next; 194 }; 195 typedef struct OpListNode OpListNode; 196 197 struct ModuleStats { 198 unsigned numOperations; 199 unsigned numAttributes; 200 unsigned numBlocks; 201 unsigned numRegions; 202 unsigned numValues; 203 unsigned numBlockArguments; 204 unsigned numOpResults; 205 }; 206 typedef struct ModuleStats ModuleStats; 207 208 int collectStatsSingle(OpListNode *head, ModuleStats *stats) { 209 MlirOperation operation = head->op; 210 stats->numOperations += 1; 211 stats->numValues += mlirOperationGetNumResults(operation); 212 stats->numAttributes += mlirOperationGetNumAttributes(operation); 213 214 unsigned numRegions = mlirOperationGetNumRegions(operation); 215 216 stats->numRegions += numRegions; 217 218 intptr_t numResults = mlirOperationGetNumResults(operation); 219 for (intptr_t i = 0; i < numResults; ++i) { 220 MlirValue result = mlirOperationGetResult(operation, i); 221 if (!mlirValueIsAOpResult(result)) 222 return 1; 223 if (mlirValueIsABlockArgument(result)) 224 return 2; 225 if (!mlirOperationEqual(operation, mlirOpResultGetOwner(result))) 226 return 3; 227 if (i != mlirOpResultGetResultNumber(result)) 228 return 4; 229 ++stats->numOpResults; 230 } 231 232 MlirRegion region = mlirOperationGetFirstRegion(operation); 233 while (!mlirRegionIsNull(region)) { 234 for (MlirBlock block = mlirRegionGetFirstBlock(region); 235 !mlirBlockIsNull(block); block = mlirBlockGetNextInRegion(block)) { 236 ++stats->numBlocks; 237 intptr_t numArgs = mlirBlockGetNumArguments(block); 238 stats->numValues += numArgs; 239 for (intptr_t j = 0; j < numArgs; ++j) { 240 MlirValue arg = mlirBlockGetArgument(block, j); 241 if (!mlirValueIsABlockArgument(arg)) 242 return 5; 243 if (mlirValueIsAOpResult(arg)) 244 return 6; 245 if (!mlirBlockEqual(block, mlirBlockArgumentGetOwner(arg))) 246 return 7; 247 if (j != mlirBlockArgumentGetArgNumber(arg)) 248 return 8; 249 ++stats->numBlockArguments; 250 } 251 252 for (MlirOperation child = mlirBlockGetFirstOperation(block); 253 !mlirOperationIsNull(child); 254 child = mlirOperationGetNextInBlock(child)) { 255 OpListNode *node = malloc(sizeof(OpListNode)); 256 node->op = child; 257 node->next = head->next; 258 head->next = node; 259 } 260 } 261 region = mlirRegionGetNextInOperation(region); 262 } 263 return 0; 264 } 265 266 int collectStats(MlirOperation operation) { 267 OpListNode *head = malloc(sizeof(OpListNode)); 268 head->op = operation; 269 head->next = NULL; 270 271 ModuleStats stats; 272 stats.numOperations = 0; 273 stats.numAttributes = 0; 274 stats.numBlocks = 0; 275 stats.numRegions = 0; 276 stats.numValues = 0; 277 stats.numBlockArguments = 0; 278 stats.numOpResults = 0; 279 280 do { 281 int retval = collectStatsSingle(head, &stats); 282 if (retval) { 283 free(head); 284 return retval; 285 } 286 OpListNode *next = head->next; 287 free(head); 288 head = next; 289 } while (head); 290 291 if (stats.numValues != stats.numBlockArguments + stats.numOpResults) 292 return 100; 293 294 fprintf(stderr, "@stats\n"); 295 fprintf(stderr, "Number of operations: %u\n", stats.numOperations); 296 fprintf(stderr, "Number of attributes: %u\n", stats.numAttributes); 297 fprintf(stderr, "Number of blocks: %u\n", stats.numBlocks); 298 fprintf(stderr, "Number of regions: %u\n", stats.numRegions); 299 fprintf(stderr, "Number of values: %u\n", stats.numValues); 300 fprintf(stderr, "Number of block arguments: %u\n", stats.numBlockArguments); 301 fprintf(stderr, "Number of op results: %u\n", stats.numOpResults); 302 // clang-format off 303 // CHECK-LABEL: @stats 304 // CHECK: Number of operations: 12 305 // CHECK: Number of attributes: 4 306 // CHECK: Number of blocks: 3 307 // CHECK: Number of regions: 3 308 // CHECK: Number of values: 9 309 // CHECK: Number of block arguments: 3 310 // CHECK: Number of op results: 6 311 // clang-format on 312 return 0; 313 } 314 315 static void printToStderr(MlirStringRef str, void *userData) { 316 (void)userData; 317 fwrite(str.data, 1, str.length, stderr); 318 } 319 320 static void printFirstOfEach(MlirContext ctx, MlirOperation operation) { 321 // Assuming we are given a module, go to the first operation of the first 322 // function. 323 MlirRegion region = mlirOperationGetRegion(operation, 0); 324 MlirBlock block = mlirRegionGetFirstBlock(region); 325 operation = mlirBlockGetFirstOperation(block); 326 region = mlirOperationGetRegion(operation, 0); 327 MlirOperation parentOperation = operation; 328 block = mlirRegionGetFirstBlock(region); 329 operation = mlirBlockGetFirstOperation(block); 330 assert(mlirModuleIsNull(mlirModuleFromOperation(operation))); 331 332 // Verify that parent operation and block report correctly. 333 // CHECK: Parent operation eq: 1 334 fprintf(stderr, "Parent operation eq: %d\n", 335 mlirOperationEqual(mlirOperationGetParentOperation(operation), 336 parentOperation)); 337 // CHECK: Block eq: 1 338 fprintf(stderr, "Block eq: %d\n", 339 mlirBlockEqual(mlirOperationGetBlock(operation), block)); 340 // CHECK: Block parent operation eq: 1 341 fprintf( 342 stderr, "Block parent operation eq: %d\n", 343 mlirOperationEqual(mlirBlockGetParentOperation(block), parentOperation)); 344 // CHECK: Block parent region eq: 1 345 fprintf(stderr, "Block parent region eq: %d\n", 346 mlirRegionEqual(mlirBlockGetParentRegion(block), region)); 347 348 // In the module we created, the first operation of the first function is 349 // an "memref.dim", which has an attribute and a single result that we can 350 // use to test the printing mechanism. 351 mlirBlockPrint(block, printToStderr, NULL); 352 fprintf(stderr, "\n"); 353 fprintf(stderr, "First operation: "); 354 mlirOperationPrint(operation, printToStderr, NULL); 355 fprintf(stderr, "\n"); 356 // clang-format off 357 // CHECK: %[[C0:.*]] = arith.constant 0 : index 358 // CHECK: %[[DIM:.*]] = memref.dim %{{.*}}, %[[C0]] : memref<?xf32> 359 // CHECK: %[[C1:.*]] = arith.constant 1 : index 360 // CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[DIM]] step %[[C1]] { 361 // CHECK: %[[LHS:.*]] = memref.load %{{.*}}[%[[I]]] : memref<?xf32> 362 // CHECK: %[[RHS:.*]] = memref.load %{{.*}}[%[[I]]] : memref<?xf32> 363 // CHECK: %[[SUM:.*]] = arith.addf %[[LHS]], %[[RHS]] : f32 364 // CHECK: memref.store %[[SUM]], %{{.*}}[%[[I]]] : memref<?xf32> 365 // CHECK: } 366 // CHECK: return 367 // CHECK: First operation: {{.*}} = arith.constant 0 : index 368 // clang-format on 369 370 // Get the operation name and print it. 371 MlirIdentifier ident = mlirOperationGetName(operation); 372 MlirStringRef identStr = mlirIdentifierStr(ident); 373 fprintf(stderr, "Operation name: '"); 374 for (size_t i = 0; i < identStr.length; ++i) 375 fputc(identStr.data[i], stderr); 376 fprintf(stderr, "'\n"); 377 // CHECK: Operation name: 'arith.constant' 378 379 // Get the identifier again and verify equal. 380 MlirIdentifier identAgain = mlirIdentifierGet(ctx, identStr); 381 fprintf(stderr, "Identifier equal: %d\n", 382 mlirIdentifierEqual(ident, identAgain)); 383 // CHECK: Identifier equal: 1 384 385 // Get the block terminator and print it. 386 MlirOperation terminator = mlirBlockGetTerminator(block); 387 fprintf(stderr, "Terminator: "); 388 mlirOperationPrint(terminator, printToStderr, NULL); 389 fprintf(stderr, "\n"); 390 // CHECK: Terminator: func.return 391 392 // Get the attribute by index. 393 MlirNamedAttribute namedAttr0 = mlirOperationGetAttribute(operation, 0); 394 fprintf(stderr, "Get attr 0: "); 395 mlirAttributePrint(namedAttr0.attribute, printToStderr, NULL); 396 fprintf(stderr, "\n"); 397 // CHECK: Get attr 0: 0 : index 398 399 // Now re-get the attribute by name. 400 MlirAttribute attr0ByName = mlirOperationGetAttributeByName( 401 operation, mlirIdentifierStr(namedAttr0.name)); 402 fprintf(stderr, "Get attr 0 by name: "); 403 mlirAttributePrint(attr0ByName, printToStderr, NULL); 404 fprintf(stderr, "\n"); 405 // CHECK: Get attr 0 by name: 0 : index 406 407 // Get a non-existing attribute and assert that it is null (sanity). 408 fprintf(stderr, "does_not_exist is null: %d\n", 409 mlirAttributeIsNull(mlirOperationGetAttributeByName( 410 operation, mlirStringRefCreateFromCString("does_not_exist")))); 411 // CHECK: does_not_exist is null: 1 412 413 // Get result 0 and its type. 414 MlirValue value = mlirOperationGetResult(operation, 0); 415 fprintf(stderr, "Result 0: "); 416 mlirValuePrint(value, printToStderr, NULL); 417 fprintf(stderr, "\n"); 418 fprintf(stderr, "Value is null: %d\n", mlirValueIsNull(value)); 419 // CHECK: Result 0: {{.*}} = arith.constant 0 : index 420 // CHECK: Value is null: 0 421 422 MlirType type = mlirValueGetType(value); 423 fprintf(stderr, "Result 0 type: "); 424 mlirTypePrint(type, printToStderr, NULL); 425 fprintf(stderr, "\n"); 426 // CHECK: Result 0 type: index 427 428 // Set a custom attribute. 429 mlirOperationSetAttributeByName(operation, 430 mlirStringRefCreateFromCString("custom_attr"), 431 mlirBoolAttrGet(ctx, 1)); 432 fprintf(stderr, "Op with set attr: "); 433 mlirOperationPrint(operation, printToStderr, NULL); 434 fprintf(stderr, "\n"); 435 // CHECK: Op with set attr: {{.*}} {custom_attr = true} 436 437 // Remove the attribute. 438 fprintf(stderr, "Remove attr: %d\n", 439 mlirOperationRemoveAttributeByName( 440 operation, mlirStringRefCreateFromCString("custom_attr"))); 441 fprintf(stderr, "Remove attr again: %d\n", 442 mlirOperationRemoveAttributeByName( 443 operation, mlirStringRefCreateFromCString("custom_attr"))); 444 fprintf(stderr, "Removed attr is null: %d\n", 445 mlirAttributeIsNull(mlirOperationGetAttributeByName( 446 operation, mlirStringRefCreateFromCString("custom_attr")))); 447 // CHECK: Remove attr: 1 448 // CHECK: Remove attr again: 0 449 // CHECK: Removed attr is null: 1 450 451 // Add a large attribute to verify printing flags. 452 int64_t eltsShape[] = {4}; 453 int32_t eltsData[] = {1, 2, 3, 4}; 454 mlirOperationSetAttributeByName( 455 operation, mlirStringRefCreateFromCString("elts"), 456 mlirDenseElementsAttrInt32Get( 457 mlirRankedTensorTypeGet(1, eltsShape, mlirIntegerTypeGet(ctx, 32), 458 mlirAttributeGetNull()), 459 4, eltsData)); 460 MlirOpPrintingFlags flags = mlirOpPrintingFlagsCreate(); 461 mlirOpPrintingFlagsElideLargeElementsAttrs(flags, 2); 462 mlirOpPrintingFlagsPrintGenericOpForm(flags); 463 mlirOpPrintingFlagsEnableDebugInfo(flags, /*prettyForm=*/0); 464 mlirOpPrintingFlagsUseLocalScope(flags); 465 fprintf(stderr, "Op print with all flags: "); 466 mlirOperationPrintWithFlags(operation, flags, printToStderr, NULL); 467 fprintf(stderr, "\n"); 468 // clang-format off 469 // CHECK: Op print with all flags: %{{.*}} = "arith.constant"() {elts = opaque<"elided_large_const", "0xDEADBEEF"> : tensor<4xi32>, value = 0 : index} : () -> index loc(unknown) 470 // clang-format on 471 472 mlirOpPrintingFlagsDestroy(flags); 473 } 474 475 static int constructAndTraverseIr(MlirContext ctx) { 476 MlirLocation location = mlirLocationUnknownGet(ctx); 477 478 MlirModule moduleOp = makeAndDumpAdd(ctx, location); 479 MlirOperation module = mlirModuleGetOperation(moduleOp); 480 assert(!mlirModuleIsNull(mlirModuleFromOperation(module))); 481 482 int errcode = collectStats(module); 483 if (errcode) 484 return errcode; 485 486 printFirstOfEach(ctx, module); 487 488 mlirModuleDestroy(moduleOp); 489 return 0; 490 } 491 492 /// Creates an operation with a region containing multiple blocks with 493 /// operations and dumps it. The blocks and operations are inserted using 494 /// block/operation-relative API and their final order is checked. 495 static void buildWithInsertionsAndPrint(MlirContext ctx) { 496 MlirLocation loc = mlirLocationUnknownGet(ctx); 497 mlirContextSetAllowUnregisteredDialects(ctx, true); 498 499 MlirRegion owningRegion = mlirRegionCreate(); 500 MlirBlock nullBlock = mlirRegionGetFirstBlock(owningRegion); 501 MlirOperationState state = mlirOperationStateGet( 502 mlirStringRefCreateFromCString("insertion.order.test"), loc); 503 mlirOperationStateAddOwnedRegions(&state, 1, &owningRegion); 504 MlirOperation op = mlirOperationCreate(&state); 505 MlirRegion region = mlirOperationGetRegion(op, 0); 506 507 // Use integer types of different bitwidth as block arguments in order to 508 // differentiate blocks. 509 MlirType i1 = mlirIntegerTypeGet(ctx, 1); 510 MlirType i2 = mlirIntegerTypeGet(ctx, 2); 511 MlirType i3 = mlirIntegerTypeGet(ctx, 3); 512 MlirType i4 = mlirIntegerTypeGet(ctx, 4); 513 MlirType i5 = mlirIntegerTypeGet(ctx, 5); 514 MlirBlock block1 = mlirBlockCreate(1, &i1, &loc); 515 MlirBlock block2 = mlirBlockCreate(1, &i2, &loc); 516 MlirBlock block3 = mlirBlockCreate(1, &i3, &loc); 517 MlirBlock block4 = mlirBlockCreate(1, &i4, &loc); 518 MlirBlock block5 = mlirBlockCreate(1, &i5, &loc); 519 // Insert blocks so as to obtain the 1-2-3-4 order, 520 mlirRegionInsertOwnedBlockBefore(region, nullBlock, block3); 521 mlirRegionInsertOwnedBlockBefore(region, block3, block2); 522 mlirRegionInsertOwnedBlockAfter(region, nullBlock, block1); 523 mlirRegionInsertOwnedBlockAfter(region, block3, block4); 524 mlirRegionInsertOwnedBlockBefore(region, block3, block5); 525 526 MlirOperationState op1State = 527 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op1"), loc); 528 MlirOperationState op2State = 529 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op2"), loc); 530 MlirOperationState op3State = 531 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op3"), loc); 532 MlirOperationState op4State = 533 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op4"), loc); 534 MlirOperationState op5State = 535 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op5"), loc); 536 MlirOperationState op6State = 537 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op6"), loc); 538 MlirOperationState op7State = 539 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op7"), loc); 540 MlirOperationState op8State = 541 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op8"), loc); 542 MlirOperation op1 = mlirOperationCreate(&op1State); 543 MlirOperation op2 = mlirOperationCreate(&op2State); 544 MlirOperation op3 = mlirOperationCreate(&op3State); 545 MlirOperation op4 = mlirOperationCreate(&op4State); 546 MlirOperation op5 = mlirOperationCreate(&op5State); 547 MlirOperation op6 = mlirOperationCreate(&op6State); 548 MlirOperation op7 = mlirOperationCreate(&op7State); 549 MlirOperation op8 = mlirOperationCreate(&op8State); 550 551 // Insert operations in the first block so as to obtain the 1-2-3-4 order. 552 MlirOperation nullOperation = mlirBlockGetFirstOperation(block1); 553 assert(mlirOperationIsNull(nullOperation)); 554 mlirBlockInsertOwnedOperationBefore(block1, nullOperation, op3); 555 mlirBlockInsertOwnedOperationBefore(block1, op3, op2); 556 mlirBlockInsertOwnedOperationAfter(block1, nullOperation, op1); 557 mlirBlockInsertOwnedOperationAfter(block1, op3, op4); 558 559 // Append operations to the rest of blocks to make them non-empty and thus 560 // printable. 561 mlirBlockAppendOwnedOperation(block2, op5); 562 mlirBlockAppendOwnedOperation(block3, op6); 563 mlirBlockAppendOwnedOperation(block4, op7); 564 mlirBlockAppendOwnedOperation(block5, op8); 565 566 // Remove block5. 567 mlirBlockDetach(block5); 568 mlirBlockDestroy(block5); 569 570 mlirOperationDump(op); 571 mlirOperationDestroy(op); 572 mlirContextSetAllowUnregisteredDialects(ctx, false); 573 // clang-format off 574 // CHECK-LABEL: "insertion.order.test" 575 // CHECK: ^{{.*}}(%{{.*}}: i1 576 // CHECK: "dummy.op1" 577 // CHECK-NEXT: "dummy.op2" 578 // CHECK-NEXT: "dummy.op3" 579 // CHECK-NEXT: "dummy.op4" 580 // CHECK: ^{{.*}}(%{{.*}}: i2 581 // CHECK: "dummy.op5" 582 // CHECK-NOT: ^{{.*}}(%{{.*}}: i5 583 // CHECK-NOT: "dummy.op8" 584 // CHECK: ^{{.*}}(%{{.*}}: i3 585 // CHECK: "dummy.op6" 586 // CHECK: ^{{.*}}(%{{.*}}: i4 587 // CHECK: "dummy.op7" 588 // clang-format on 589 } 590 591 /// Creates operations with type inference and tests various failure modes. 592 static int createOperationWithTypeInference(MlirContext ctx) { 593 MlirLocation loc = mlirLocationUnknownGet(ctx); 594 MlirAttribute iAttr = mlirIntegerAttrGet(mlirIntegerTypeGet(ctx, 32), 4); 595 596 // The shape.const_size op implements result type inference and is only used 597 // for that reason. 598 MlirOperationState state = mlirOperationStateGet( 599 mlirStringRefCreateFromCString("shape.const_size"), loc); 600 MlirNamedAttribute valueAttr = mlirNamedAttributeGet( 601 mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")), iAttr); 602 mlirOperationStateAddAttributes(&state, 1, &valueAttr); 603 mlirOperationStateEnableResultTypeInference(&state); 604 605 // Expect result type inference to succeed. 606 MlirOperation op = mlirOperationCreate(&state); 607 if (mlirOperationIsNull(op)) { 608 fprintf(stderr, "ERROR: Result type inference unexpectedly failed"); 609 return 1; 610 } 611 612 // CHECK: RESULT_TYPE_INFERENCE: !shape.size 613 fprintf(stderr, "RESULT_TYPE_INFERENCE: "); 614 mlirTypeDump(mlirValueGetType(mlirOperationGetResult(op, 0))); 615 fprintf(stderr, "\n"); 616 mlirOperationDestroy(op); 617 return 0; 618 } 619 620 /// Dumps instances of all builtin types to check that C API works correctly. 621 /// Additionally, performs simple identity checks that a builtin type 622 /// constructed with C API can be inspected and has the expected type. The 623 /// latter achieves full coverage of C API for builtin types. Returns 0 on 624 /// success and a non-zero error code on failure. 625 static int printBuiltinTypes(MlirContext ctx) { 626 // Integer types. 627 MlirType i32 = mlirIntegerTypeGet(ctx, 32); 628 MlirType si32 = mlirIntegerTypeSignedGet(ctx, 32); 629 MlirType ui32 = mlirIntegerTypeUnsignedGet(ctx, 32); 630 if (!mlirTypeIsAInteger(i32) || mlirTypeIsAF32(i32)) 631 return 1; 632 if (!mlirTypeIsAInteger(si32) || !mlirIntegerTypeIsSigned(si32)) 633 return 2; 634 if (!mlirTypeIsAInteger(ui32) || !mlirIntegerTypeIsUnsigned(ui32)) 635 return 3; 636 if (mlirTypeEqual(i32, ui32) || mlirTypeEqual(i32, si32)) 637 return 4; 638 if (mlirIntegerTypeGetWidth(i32) != mlirIntegerTypeGetWidth(si32)) 639 return 5; 640 fprintf(stderr, "@types\n"); 641 mlirTypeDump(i32); 642 fprintf(stderr, "\n"); 643 mlirTypeDump(si32); 644 fprintf(stderr, "\n"); 645 mlirTypeDump(ui32); 646 fprintf(stderr, "\n"); 647 // CHECK-LABEL: @types 648 // CHECK: i32 649 // CHECK: si32 650 // CHECK: ui32 651 652 // Index type. 653 MlirType index = mlirIndexTypeGet(ctx); 654 if (!mlirTypeIsAIndex(index)) 655 return 6; 656 mlirTypeDump(index); 657 fprintf(stderr, "\n"); 658 // CHECK: index 659 660 // Floating-point types. 661 MlirType bf16 = mlirBF16TypeGet(ctx); 662 MlirType f16 = mlirF16TypeGet(ctx); 663 MlirType f32 = mlirF32TypeGet(ctx); 664 MlirType f64 = mlirF64TypeGet(ctx); 665 if (!mlirTypeIsABF16(bf16)) 666 return 7; 667 if (!mlirTypeIsAF16(f16)) 668 return 9; 669 if (!mlirTypeIsAF32(f32)) 670 return 10; 671 if (!mlirTypeIsAF64(f64)) 672 return 11; 673 mlirTypeDump(bf16); 674 fprintf(stderr, "\n"); 675 mlirTypeDump(f16); 676 fprintf(stderr, "\n"); 677 mlirTypeDump(f32); 678 fprintf(stderr, "\n"); 679 mlirTypeDump(f64); 680 fprintf(stderr, "\n"); 681 // CHECK: bf16 682 // CHECK: f16 683 // CHECK: f32 684 // CHECK: f64 685 686 // None type. 687 MlirType none = mlirNoneTypeGet(ctx); 688 if (!mlirTypeIsANone(none)) 689 return 12; 690 mlirTypeDump(none); 691 fprintf(stderr, "\n"); 692 // CHECK: none 693 694 // Complex type. 695 MlirType cplx = mlirComplexTypeGet(f32); 696 if (!mlirTypeIsAComplex(cplx) || 697 !mlirTypeEqual(mlirComplexTypeGetElementType(cplx), f32)) 698 return 13; 699 mlirTypeDump(cplx); 700 fprintf(stderr, "\n"); 701 // CHECK: complex<f32> 702 703 // Vector (and Shaped) type. ShapedType is a common base class for vectors, 704 // memrefs and tensors, one cannot create instances of this class so it is 705 // tested on an instance of vector type. 706 int64_t shape[] = {2, 3}; 707 MlirType vector = 708 mlirVectorTypeGet(sizeof(shape) / sizeof(int64_t), shape, f32); 709 if (!mlirTypeIsAVector(vector) || !mlirTypeIsAShaped(vector)) 710 return 14; 711 if (!mlirTypeEqual(mlirShapedTypeGetElementType(vector), f32) || 712 !mlirShapedTypeHasRank(vector) || mlirShapedTypeGetRank(vector) != 2 || 713 mlirShapedTypeGetDimSize(vector, 0) != 2 || 714 mlirShapedTypeIsDynamicDim(vector, 0) || 715 mlirShapedTypeGetDimSize(vector, 1) != 3 || 716 !mlirShapedTypeHasStaticShape(vector)) 717 return 15; 718 mlirTypeDump(vector); 719 fprintf(stderr, "\n"); 720 // CHECK: vector<2x3xf32> 721 722 // Ranked tensor type. 723 MlirType rankedTensor = mlirRankedTensorTypeGet( 724 sizeof(shape) / sizeof(int64_t), shape, f32, mlirAttributeGetNull()); 725 if (!mlirTypeIsATensor(rankedTensor) || 726 !mlirTypeIsARankedTensor(rankedTensor) || 727 !mlirAttributeIsNull(mlirRankedTensorTypeGetEncoding(rankedTensor))) 728 return 16; 729 mlirTypeDump(rankedTensor); 730 fprintf(stderr, "\n"); 731 // CHECK: tensor<2x3xf32> 732 733 // Unranked tensor type. 734 MlirType unrankedTensor = mlirUnrankedTensorTypeGet(f32); 735 if (!mlirTypeIsATensor(unrankedTensor) || 736 !mlirTypeIsAUnrankedTensor(unrankedTensor) || 737 mlirShapedTypeHasRank(unrankedTensor)) 738 return 17; 739 mlirTypeDump(unrankedTensor); 740 fprintf(stderr, "\n"); 741 // CHECK: tensor<*xf32> 742 743 // MemRef type. 744 MlirAttribute memSpace2 = mlirIntegerAttrGet(mlirIntegerTypeGet(ctx, 64), 2); 745 MlirType memRef = mlirMemRefTypeContiguousGet( 746 f32, sizeof(shape) / sizeof(int64_t), shape, memSpace2); 747 if (!mlirTypeIsAMemRef(memRef) || 748 !mlirAttributeEqual(mlirMemRefTypeGetMemorySpace(memRef), memSpace2)) 749 return 18; 750 mlirTypeDump(memRef); 751 fprintf(stderr, "\n"); 752 // CHECK: memref<2x3xf32, 2> 753 754 // Unranked MemRef type. 755 MlirAttribute memSpace4 = mlirIntegerAttrGet(mlirIntegerTypeGet(ctx, 64), 4); 756 MlirType unrankedMemRef = mlirUnrankedMemRefTypeGet(f32, memSpace4); 757 if (!mlirTypeIsAUnrankedMemRef(unrankedMemRef) || 758 mlirTypeIsAMemRef(unrankedMemRef) || 759 !mlirAttributeEqual(mlirUnrankedMemrefGetMemorySpace(unrankedMemRef), 760 memSpace4)) 761 return 19; 762 mlirTypeDump(unrankedMemRef); 763 fprintf(stderr, "\n"); 764 // CHECK: memref<*xf32, 4> 765 766 // Tuple type. 767 MlirType types[] = {unrankedMemRef, f32}; 768 MlirType tuple = mlirTupleTypeGet(ctx, 2, types); 769 if (!mlirTypeIsATuple(tuple) || mlirTupleTypeGetNumTypes(tuple) != 2 || 770 !mlirTypeEqual(mlirTupleTypeGetType(tuple, 0), unrankedMemRef) || 771 !mlirTypeEqual(mlirTupleTypeGetType(tuple, 1), f32)) 772 return 20; 773 mlirTypeDump(tuple); 774 fprintf(stderr, "\n"); 775 // CHECK: tuple<memref<*xf32, 4>, f32> 776 777 // Function type. 778 MlirType funcInputs[2] = {mlirIndexTypeGet(ctx), mlirIntegerTypeGet(ctx, 1)}; 779 MlirType funcResults[3] = {mlirIntegerTypeGet(ctx, 16), 780 mlirIntegerTypeGet(ctx, 32), 781 mlirIntegerTypeGet(ctx, 64)}; 782 MlirType funcType = mlirFunctionTypeGet(ctx, 2, funcInputs, 3, funcResults); 783 if (mlirFunctionTypeGetNumInputs(funcType) != 2) 784 return 21; 785 if (mlirFunctionTypeGetNumResults(funcType) != 3) 786 return 22; 787 if (!mlirTypeEqual(funcInputs[0], mlirFunctionTypeGetInput(funcType, 0)) || 788 !mlirTypeEqual(funcInputs[1], mlirFunctionTypeGetInput(funcType, 1))) 789 return 23; 790 if (!mlirTypeEqual(funcResults[0], mlirFunctionTypeGetResult(funcType, 0)) || 791 !mlirTypeEqual(funcResults[1], mlirFunctionTypeGetResult(funcType, 1)) || 792 !mlirTypeEqual(funcResults[2], mlirFunctionTypeGetResult(funcType, 2))) 793 return 24; 794 mlirTypeDump(funcType); 795 fprintf(stderr, "\n"); 796 // CHECK: (index, i1) -> (i16, i32, i64) 797 798 return 0; 799 } 800 801 void callbackSetFixedLengthString(const char *data, intptr_t len, 802 void *userData) { 803 strncpy(userData, data, len); 804 } 805 806 bool stringIsEqual(const char *lhs, MlirStringRef rhs) { 807 if (strlen(lhs) != rhs.length) { 808 return false; 809 } 810 return !strncmp(lhs, rhs.data, rhs.length); 811 } 812 813 int printBuiltinAttributes(MlirContext ctx) { 814 MlirAttribute floating = 815 mlirFloatAttrDoubleGet(ctx, mlirF64TypeGet(ctx), 2.0); 816 if (!mlirAttributeIsAFloat(floating) || 817 fabs(mlirFloatAttrGetValueDouble(floating) - 2.0) > 1E-6) 818 return 1; 819 fprintf(stderr, "@attrs\n"); 820 mlirAttributeDump(floating); 821 // CHECK-LABEL: @attrs 822 // CHECK: 2.000000e+00 : f64 823 824 // Exercise mlirAttributeGetType() just for the first one. 825 MlirType floatingType = mlirAttributeGetType(floating); 826 mlirTypeDump(floatingType); 827 // CHECK: f64 828 829 MlirAttribute integer = mlirIntegerAttrGet(mlirIntegerTypeGet(ctx, 32), 42); 830 MlirAttribute signedInteger = 831 mlirIntegerAttrGet(mlirIntegerTypeSignedGet(ctx, 8), -1); 832 MlirAttribute unsignedInteger = 833 mlirIntegerAttrGet(mlirIntegerTypeUnsignedGet(ctx, 8), 255); 834 if (!mlirAttributeIsAInteger(integer) || 835 mlirIntegerAttrGetValueInt(integer) != 42 || 836 mlirIntegerAttrGetValueSInt(signedInteger) != -1 || 837 mlirIntegerAttrGetValueUInt(unsignedInteger) != 255) 838 return 2; 839 mlirAttributeDump(integer); 840 mlirAttributeDump(signedInteger); 841 mlirAttributeDump(unsignedInteger); 842 // CHECK: 42 : i32 843 // CHECK: -1 : si8 844 // CHECK: 255 : ui8 845 846 MlirAttribute boolean = mlirBoolAttrGet(ctx, 1); 847 if (!mlirAttributeIsABool(boolean) || !mlirBoolAttrGetValue(boolean)) 848 return 3; 849 mlirAttributeDump(boolean); 850 // CHECK: true 851 852 const char data[] = "abcdefghijklmnopqestuvwxyz"; 853 MlirAttribute opaque = 854 mlirOpaqueAttrGet(ctx, mlirStringRefCreateFromCString("func"), 3, data, 855 mlirNoneTypeGet(ctx)); 856 if (!mlirAttributeIsAOpaque(opaque) || 857 !stringIsEqual("func", mlirOpaqueAttrGetDialectNamespace(opaque))) 858 return 4; 859 860 MlirStringRef opaqueData = mlirOpaqueAttrGetData(opaque); 861 if (opaqueData.length != 3 || 862 strncmp(data, opaqueData.data, opaqueData.length)) 863 return 5; 864 mlirAttributeDump(opaque); 865 // CHECK: #func.abc 866 867 MlirAttribute string = 868 mlirStringAttrGet(ctx, mlirStringRefCreate(data + 3, 2)); 869 if (!mlirAttributeIsAString(string)) 870 return 6; 871 872 MlirStringRef stringValue = mlirStringAttrGetValue(string); 873 if (stringValue.length != 2 || 874 strncmp(data + 3, stringValue.data, stringValue.length)) 875 return 7; 876 mlirAttributeDump(string); 877 // CHECK: "de" 878 879 MlirAttribute flatSymbolRef = 880 mlirFlatSymbolRefAttrGet(ctx, mlirStringRefCreate(data + 5, 3)); 881 if (!mlirAttributeIsAFlatSymbolRef(flatSymbolRef)) 882 return 8; 883 884 MlirStringRef flatSymbolRefValue = 885 mlirFlatSymbolRefAttrGetValue(flatSymbolRef); 886 if (flatSymbolRefValue.length != 3 || 887 strncmp(data + 5, flatSymbolRefValue.data, flatSymbolRefValue.length)) 888 return 9; 889 mlirAttributeDump(flatSymbolRef); 890 // CHECK: @fgh 891 892 MlirAttribute symbols[] = {flatSymbolRef, flatSymbolRef}; 893 MlirAttribute symbolRef = 894 mlirSymbolRefAttrGet(ctx, mlirStringRefCreate(data + 8, 2), 2, symbols); 895 if (!mlirAttributeIsASymbolRef(symbolRef) || 896 mlirSymbolRefAttrGetNumNestedReferences(symbolRef) != 2 || 897 !mlirAttributeEqual(mlirSymbolRefAttrGetNestedReference(symbolRef, 0), 898 flatSymbolRef) || 899 !mlirAttributeEqual(mlirSymbolRefAttrGetNestedReference(symbolRef, 1), 900 flatSymbolRef)) 901 return 10; 902 903 MlirStringRef symbolRefLeaf = mlirSymbolRefAttrGetLeafReference(symbolRef); 904 MlirStringRef symbolRefRoot = mlirSymbolRefAttrGetRootReference(symbolRef); 905 if (symbolRefLeaf.length != 3 || 906 strncmp(data + 5, symbolRefLeaf.data, symbolRefLeaf.length) || 907 symbolRefRoot.length != 2 || 908 strncmp(data + 8, symbolRefRoot.data, symbolRefRoot.length)) 909 return 11; 910 mlirAttributeDump(symbolRef); 911 // CHECK: @ij::@fgh::@fgh 912 913 MlirAttribute type = mlirTypeAttrGet(mlirF32TypeGet(ctx)); 914 if (!mlirAttributeIsAType(type) || 915 !mlirTypeEqual(mlirF32TypeGet(ctx), mlirTypeAttrGetValue(type))) 916 return 12; 917 mlirAttributeDump(type); 918 // CHECK: f32 919 920 MlirAttribute unit = mlirUnitAttrGet(ctx); 921 if (!mlirAttributeIsAUnit(unit)) 922 return 13; 923 mlirAttributeDump(unit); 924 // CHECK: unit 925 926 int64_t shape[] = {1, 2}; 927 928 int bools[] = {0, 1}; 929 uint8_t uints8[] = {0u, 1u}; 930 int8_t ints8[] = {0, 1}; 931 uint16_t uints16[] = {0u, 1u}; 932 int16_t ints16[] = {0, 1}; 933 uint32_t uints32[] = {0u, 1u}; 934 int32_t ints32[] = {0, 1}; 935 uint64_t uints64[] = {0u, 1u}; 936 int64_t ints64[] = {0, 1}; 937 float floats[] = {0.0f, 1.0f}; 938 double doubles[] = {0.0, 1.0}; 939 uint16_t bf16s[] = {0x0, 0x3f80}; 940 MlirAttribute encoding = mlirAttributeGetNull(); 941 MlirAttribute boolElements = mlirDenseElementsAttrBoolGet( 942 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 1), encoding), 943 2, bools); 944 MlirAttribute uint8Elements = mlirDenseElementsAttrUInt8Get( 945 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 8), 946 encoding), 947 2, uints8); 948 MlirAttribute int8Elements = mlirDenseElementsAttrInt8Get( 949 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 8), encoding), 950 2, ints8); 951 MlirAttribute uint16Elements = mlirDenseElementsAttrUInt16Get( 952 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 16), 953 encoding), 954 2, uints16); 955 MlirAttribute int16Elements = mlirDenseElementsAttrInt16Get( 956 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 16), encoding), 957 2, ints16); 958 MlirAttribute uint32Elements = mlirDenseElementsAttrUInt32Get( 959 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 32), 960 encoding), 961 2, uints32); 962 MlirAttribute int32Elements = mlirDenseElementsAttrInt32Get( 963 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 32), encoding), 964 2, ints32); 965 MlirAttribute uint64Elements = mlirDenseElementsAttrUInt64Get( 966 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 64), 967 encoding), 968 2, uints64); 969 MlirAttribute int64Elements = mlirDenseElementsAttrInt64Get( 970 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64), encoding), 971 2, ints64); 972 MlirAttribute floatElements = mlirDenseElementsAttrFloatGet( 973 mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx), encoding), 2, 974 floats); 975 MlirAttribute doubleElements = mlirDenseElementsAttrDoubleGet( 976 mlirRankedTensorTypeGet(2, shape, mlirF64TypeGet(ctx), encoding), 2, 977 doubles); 978 MlirAttribute bf16Elements = mlirDenseElementsAttrBFloat16Get( 979 mlirRankedTensorTypeGet(2, shape, mlirBF16TypeGet(ctx), encoding), 2, 980 bf16s); 981 982 if (!mlirAttributeIsADenseElements(boolElements) || 983 !mlirAttributeIsADenseElements(uint8Elements) || 984 !mlirAttributeIsADenseElements(int8Elements) || 985 !mlirAttributeIsADenseElements(uint32Elements) || 986 !mlirAttributeIsADenseElements(int32Elements) || 987 !mlirAttributeIsADenseElements(uint64Elements) || 988 !mlirAttributeIsADenseElements(int64Elements) || 989 !mlirAttributeIsADenseElements(floatElements) || 990 !mlirAttributeIsADenseElements(doubleElements) || 991 !mlirAttributeIsADenseElements(bf16Elements)) 992 return 14; 993 994 if (mlirDenseElementsAttrGetBoolValue(boolElements, 1) != 1 || 995 mlirDenseElementsAttrGetUInt8Value(uint8Elements, 1) != 1 || 996 mlirDenseElementsAttrGetInt8Value(int8Elements, 1) != 1 || 997 mlirDenseElementsAttrGetUInt16Value(uint16Elements, 1) != 1 || 998 mlirDenseElementsAttrGetInt16Value(int16Elements, 1) != 1 || 999 mlirDenseElementsAttrGetUInt32Value(uint32Elements, 1) != 1 || 1000 mlirDenseElementsAttrGetInt32Value(int32Elements, 1) != 1 || 1001 mlirDenseElementsAttrGetUInt64Value(uint64Elements, 1) != 1 || 1002 mlirDenseElementsAttrGetInt64Value(int64Elements, 1) != 1 || 1003 fabsf(mlirDenseElementsAttrGetFloatValue(floatElements, 1) - 1.0f) > 1004 1E-6f || 1005 fabs(mlirDenseElementsAttrGetDoubleValue(doubleElements, 1) - 1.0) > 1E-6) 1006 return 15; 1007 1008 mlirAttributeDump(boolElements); 1009 mlirAttributeDump(uint8Elements); 1010 mlirAttributeDump(int8Elements); 1011 mlirAttributeDump(uint32Elements); 1012 mlirAttributeDump(int32Elements); 1013 mlirAttributeDump(uint64Elements); 1014 mlirAttributeDump(int64Elements); 1015 mlirAttributeDump(floatElements); 1016 mlirAttributeDump(doubleElements); 1017 mlirAttributeDump(bf16Elements); 1018 // CHECK: dense<{{\[}}[false, true]]> : tensor<1x2xi1> 1019 // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui8> 1020 // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi8> 1021 // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui32> 1022 // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi32> 1023 // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xui64> 1024 // CHECK: dense<{{\[}}[0, 1]]> : tensor<1x2xi64> 1025 // CHECK: dense<{{\[}}[0.000000e+00, 1.000000e+00]]> : tensor<1x2xf32> 1026 // CHECK: dense<{{\[}}[0.000000e+00, 1.000000e+00]]> : tensor<1x2xf64> 1027 // CHECK: dense<{{\[}}[0.000000e+00, 1.000000e+00]]> : tensor<1x2xbf16> 1028 1029 MlirAttribute splatBool = mlirDenseElementsAttrBoolSplatGet( 1030 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 1), encoding), 1031 1); 1032 MlirAttribute splatUInt8 = mlirDenseElementsAttrUInt8SplatGet( 1033 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 8), 1034 encoding), 1035 1); 1036 MlirAttribute splatInt8 = mlirDenseElementsAttrInt8SplatGet( 1037 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 8), encoding), 1038 1); 1039 MlirAttribute splatUInt32 = mlirDenseElementsAttrUInt32SplatGet( 1040 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 32), 1041 encoding), 1042 1); 1043 MlirAttribute splatInt32 = mlirDenseElementsAttrInt32SplatGet( 1044 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 32), encoding), 1045 1); 1046 MlirAttribute splatUInt64 = mlirDenseElementsAttrUInt64SplatGet( 1047 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeUnsignedGet(ctx, 64), 1048 encoding), 1049 1); 1050 MlirAttribute splatInt64 = mlirDenseElementsAttrInt64SplatGet( 1051 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64), encoding), 1052 1); 1053 MlirAttribute splatFloat = mlirDenseElementsAttrFloatSplatGet( 1054 mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx), encoding), 1.0f); 1055 MlirAttribute splatDouble = mlirDenseElementsAttrDoubleSplatGet( 1056 mlirRankedTensorTypeGet(2, shape, mlirF64TypeGet(ctx), encoding), 1.0); 1057 1058 if (!mlirAttributeIsADenseElements(splatBool) || 1059 !mlirDenseElementsAttrIsSplat(splatBool) || 1060 !mlirAttributeIsADenseElements(splatUInt8) || 1061 !mlirDenseElementsAttrIsSplat(splatUInt8) || 1062 !mlirAttributeIsADenseElements(splatInt8) || 1063 !mlirDenseElementsAttrIsSplat(splatInt8) || 1064 !mlirAttributeIsADenseElements(splatUInt32) || 1065 !mlirDenseElementsAttrIsSplat(splatUInt32) || 1066 !mlirAttributeIsADenseElements(splatInt32) || 1067 !mlirDenseElementsAttrIsSplat(splatInt32) || 1068 !mlirAttributeIsADenseElements(splatUInt64) || 1069 !mlirDenseElementsAttrIsSplat(splatUInt64) || 1070 !mlirAttributeIsADenseElements(splatInt64) || 1071 !mlirDenseElementsAttrIsSplat(splatInt64) || 1072 !mlirAttributeIsADenseElements(splatFloat) || 1073 !mlirDenseElementsAttrIsSplat(splatFloat) || 1074 !mlirAttributeIsADenseElements(splatDouble) || 1075 !mlirDenseElementsAttrIsSplat(splatDouble)) 1076 return 16; 1077 1078 if (mlirDenseElementsAttrGetBoolSplatValue(splatBool) != 1 || 1079 mlirDenseElementsAttrGetUInt8SplatValue(splatUInt8) != 1 || 1080 mlirDenseElementsAttrGetInt8SplatValue(splatInt8) != 1 || 1081 mlirDenseElementsAttrGetUInt32SplatValue(splatUInt32) != 1 || 1082 mlirDenseElementsAttrGetInt32SplatValue(splatInt32) != 1 || 1083 mlirDenseElementsAttrGetUInt64SplatValue(splatUInt64) != 1 || 1084 mlirDenseElementsAttrGetInt64SplatValue(splatInt64) != 1 || 1085 fabsf(mlirDenseElementsAttrGetFloatSplatValue(splatFloat) - 1.0f) > 1086 1E-6f || 1087 fabs(mlirDenseElementsAttrGetDoubleSplatValue(splatDouble) - 1.0) > 1E-6) 1088 return 17; 1089 1090 uint8_t *uint8RawData = 1091 (uint8_t *)mlirDenseElementsAttrGetRawData(uint8Elements); 1092 int8_t *int8RawData = (int8_t *)mlirDenseElementsAttrGetRawData(int8Elements); 1093 uint32_t *uint32RawData = 1094 (uint32_t *)mlirDenseElementsAttrGetRawData(uint32Elements); 1095 int32_t *int32RawData = 1096 (int32_t *)mlirDenseElementsAttrGetRawData(int32Elements); 1097 uint64_t *uint64RawData = 1098 (uint64_t *)mlirDenseElementsAttrGetRawData(uint64Elements); 1099 int64_t *int64RawData = 1100 (int64_t *)mlirDenseElementsAttrGetRawData(int64Elements); 1101 float *floatRawData = (float *)mlirDenseElementsAttrGetRawData(floatElements); 1102 double *doubleRawData = 1103 (double *)mlirDenseElementsAttrGetRawData(doubleElements); 1104 uint16_t *bf16RawData = 1105 (uint16_t *)mlirDenseElementsAttrGetRawData(bf16Elements); 1106 if (uint8RawData[0] != 0u || uint8RawData[1] != 1u || int8RawData[0] != 0 || 1107 int8RawData[1] != 1 || uint32RawData[0] != 0u || uint32RawData[1] != 1u || 1108 int32RawData[0] != 0 || int32RawData[1] != 1 || uint64RawData[0] != 0u || 1109 uint64RawData[1] != 1u || int64RawData[0] != 0 || int64RawData[1] != 1 || 1110 floatRawData[0] != 0.0f || floatRawData[1] != 1.0f || 1111 doubleRawData[0] != 0.0 || doubleRawData[1] != 1.0 || 1112 bf16RawData[0] != 0 || bf16RawData[1] != 0x3f80) 1113 return 18; 1114 1115 mlirAttributeDump(splatBool); 1116 mlirAttributeDump(splatUInt8); 1117 mlirAttributeDump(splatInt8); 1118 mlirAttributeDump(splatUInt32); 1119 mlirAttributeDump(splatInt32); 1120 mlirAttributeDump(splatUInt64); 1121 mlirAttributeDump(splatInt64); 1122 mlirAttributeDump(splatFloat); 1123 mlirAttributeDump(splatDouble); 1124 // CHECK: dense<true> : tensor<1x2xi1> 1125 // CHECK: dense<1> : tensor<1x2xui8> 1126 // CHECK: dense<1> : tensor<1x2xi8> 1127 // CHECK: dense<1> : tensor<1x2xui32> 1128 // CHECK: dense<1> : tensor<1x2xi32> 1129 // CHECK: dense<1> : tensor<1x2xui64> 1130 // CHECK: dense<1> : tensor<1x2xi64> 1131 // CHECK: dense<1.000000e+00> : tensor<1x2xf32> 1132 // CHECK: dense<1.000000e+00> : tensor<1x2xf64> 1133 1134 mlirAttributeDump(mlirElementsAttrGetValue(floatElements, 2, uints64)); 1135 mlirAttributeDump(mlirElementsAttrGetValue(doubleElements, 2, uints64)); 1136 mlirAttributeDump(mlirElementsAttrGetValue(bf16Elements, 2, uints64)); 1137 // CHECK: 1.000000e+00 : f32 1138 // CHECK: 1.000000e+00 : f64 1139 // CHECK: 1.000000e+00 : bf16 1140 1141 int64_t indices[] = {0, 1}; 1142 int64_t one = 1; 1143 MlirAttribute indicesAttr = mlirDenseElementsAttrInt64Get( 1144 mlirRankedTensorTypeGet(2, shape, mlirIntegerTypeGet(ctx, 64), encoding), 1145 2, indices); 1146 MlirAttribute valuesAttr = mlirDenseElementsAttrFloatGet( 1147 mlirRankedTensorTypeGet(1, &one, mlirF32TypeGet(ctx), encoding), 1, 1148 floats); 1149 MlirAttribute sparseAttr = mlirSparseElementsAttribute( 1150 mlirRankedTensorTypeGet(2, shape, mlirF32TypeGet(ctx), encoding), 1151 indicesAttr, valuesAttr); 1152 mlirAttributeDump(sparseAttr); 1153 // CHECK: sparse<{{\[}}[0, 1]], 0.000000e+00> : tensor<1x2xf32> 1154 1155 return 0; 1156 } 1157 1158 int printAffineMap(MlirContext ctx) { 1159 MlirAffineMap emptyAffineMap = mlirAffineMapEmptyGet(ctx); 1160 MlirAffineMap affineMap = mlirAffineMapZeroResultGet(ctx, 3, 2); 1161 MlirAffineMap constAffineMap = mlirAffineMapConstantGet(ctx, 2); 1162 MlirAffineMap multiDimIdentityAffineMap = 1163 mlirAffineMapMultiDimIdentityGet(ctx, 3); 1164 MlirAffineMap minorIdentityAffineMap = 1165 mlirAffineMapMinorIdentityGet(ctx, 3, 2); 1166 unsigned permutation[] = {1, 2, 0}; 1167 MlirAffineMap permutationAffineMap = mlirAffineMapPermutationGet( 1168 ctx, sizeof(permutation) / sizeof(unsigned), permutation); 1169 1170 fprintf(stderr, "@affineMap\n"); 1171 mlirAffineMapDump(emptyAffineMap); 1172 mlirAffineMapDump(affineMap); 1173 mlirAffineMapDump(constAffineMap); 1174 mlirAffineMapDump(multiDimIdentityAffineMap); 1175 mlirAffineMapDump(minorIdentityAffineMap); 1176 mlirAffineMapDump(permutationAffineMap); 1177 // CHECK-LABEL: @affineMap 1178 // CHECK: () -> () 1179 // CHECK: (d0, d1, d2)[s0, s1] -> () 1180 // CHECK: () -> (2) 1181 // CHECK: (d0, d1, d2) -> (d0, d1, d2) 1182 // CHECK: (d0, d1, d2) -> (d1, d2) 1183 // CHECK: (d0, d1, d2) -> (d1, d2, d0) 1184 1185 if (!mlirAffineMapIsIdentity(emptyAffineMap) || 1186 mlirAffineMapIsIdentity(affineMap) || 1187 mlirAffineMapIsIdentity(constAffineMap) || 1188 !mlirAffineMapIsIdentity(multiDimIdentityAffineMap) || 1189 mlirAffineMapIsIdentity(minorIdentityAffineMap) || 1190 mlirAffineMapIsIdentity(permutationAffineMap)) 1191 return 1; 1192 1193 if (!mlirAffineMapIsMinorIdentity(emptyAffineMap) || 1194 mlirAffineMapIsMinorIdentity(affineMap) || 1195 !mlirAffineMapIsMinorIdentity(multiDimIdentityAffineMap) || 1196 !mlirAffineMapIsMinorIdentity(minorIdentityAffineMap) || 1197 mlirAffineMapIsMinorIdentity(permutationAffineMap)) 1198 return 2; 1199 1200 if (!mlirAffineMapIsEmpty(emptyAffineMap) || 1201 mlirAffineMapIsEmpty(affineMap) || mlirAffineMapIsEmpty(constAffineMap) || 1202 mlirAffineMapIsEmpty(multiDimIdentityAffineMap) || 1203 mlirAffineMapIsEmpty(minorIdentityAffineMap) || 1204 mlirAffineMapIsEmpty(permutationAffineMap)) 1205 return 3; 1206 1207 if (mlirAffineMapIsSingleConstant(emptyAffineMap) || 1208 mlirAffineMapIsSingleConstant(affineMap) || 1209 !mlirAffineMapIsSingleConstant(constAffineMap) || 1210 mlirAffineMapIsSingleConstant(multiDimIdentityAffineMap) || 1211 mlirAffineMapIsSingleConstant(minorIdentityAffineMap) || 1212 mlirAffineMapIsSingleConstant(permutationAffineMap)) 1213 return 4; 1214 1215 if (mlirAffineMapGetSingleConstantResult(constAffineMap) != 2) 1216 return 5; 1217 1218 if (mlirAffineMapGetNumDims(emptyAffineMap) != 0 || 1219 mlirAffineMapGetNumDims(affineMap) != 3 || 1220 mlirAffineMapGetNumDims(constAffineMap) != 0 || 1221 mlirAffineMapGetNumDims(multiDimIdentityAffineMap) != 3 || 1222 mlirAffineMapGetNumDims(minorIdentityAffineMap) != 3 || 1223 mlirAffineMapGetNumDims(permutationAffineMap) != 3) 1224 return 6; 1225 1226 if (mlirAffineMapGetNumSymbols(emptyAffineMap) != 0 || 1227 mlirAffineMapGetNumSymbols(affineMap) != 2 || 1228 mlirAffineMapGetNumSymbols(constAffineMap) != 0 || 1229 mlirAffineMapGetNumSymbols(multiDimIdentityAffineMap) != 0 || 1230 mlirAffineMapGetNumSymbols(minorIdentityAffineMap) != 0 || 1231 mlirAffineMapGetNumSymbols(permutationAffineMap) != 0) 1232 return 7; 1233 1234 if (mlirAffineMapGetNumResults(emptyAffineMap) != 0 || 1235 mlirAffineMapGetNumResults(affineMap) != 0 || 1236 mlirAffineMapGetNumResults(constAffineMap) != 1 || 1237 mlirAffineMapGetNumResults(multiDimIdentityAffineMap) != 3 || 1238 mlirAffineMapGetNumResults(minorIdentityAffineMap) != 2 || 1239 mlirAffineMapGetNumResults(permutationAffineMap) != 3) 1240 return 8; 1241 1242 if (mlirAffineMapGetNumInputs(emptyAffineMap) != 0 || 1243 mlirAffineMapGetNumInputs(affineMap) != 5 || 1244 mlirAffineMapGetNumInputs(constAffineMap) != 0 || 1245 mlirAffineMapGetNumInputs(multiDimIdentityAffineMap) != 3 || 1246 mlirAffineMapGetNumInputs(minorIdentityAffineMap) != 3 || 1247 mlirAffineMapGetNumInputs(permutationAffineMap) != 3) 1248 return 9; 1249 1250 if (!mlirAffineMapIsProjectedPermutation(emptyAffineMap) || 1251 !mlirAffineMapIsPermutation(emptyAffineMap) || 1252 mlirAffineMapIsProjectedPermutation(affineMap) || 1253 mlirAffineMapIsPermutation(affineMap) || 1254 mlirAffineMapIsProjectedPermutation(constAffineMap) || 1255 mlirAffineMapIsPermutation(constAffineMap) || 1256 !mlirAffineMapIsProjectedPermutation(multiDimIdentityAffineMap) || 1257 !mlirAffineMapIsPermutation(multiDimIdentityAffineMap) || 1258 !mlirAffineMapIsProjectedPermutation(minorIdentityAffineMap) || 1259 mlirAffineMapIsPermutation(minorIdentityAffineMap) || 1260 !mlirAffineMapIsProjectedPermutation(permutationAffineMap) || 1261 !mlirAffineMapIsPermutation(permutationAffineMap)) 1262 return 10; 1263 1264 intptr_t sub[] = {1}; 1265 1266 MlirAffineMap subMap = mlirAffineMapGetSubMap( 1267 multiDimIdentityAffineMap, sizeof(sub) / sizeof(intptr_t), sub); 1268 MlirAffineMap majorSubMap = 1269 mlirAffineMapGetMajorSubMap(multiDimIdentityAffineMap, 1); 1270 MlirAffineMap minorSubMap = 1271 mlirAffineMapGetMinorSubMap(multiDimIdentityAffineMap, 1); 1272 1273 mlirAffineMapDump(subMap); 1274 mlirAffineMapDump(majorSubMap); 1275 mlirAffineMapDump(minorSubMap); 1276 // CHECK: (d0, d1, d2) -> (d1) 1277 // CHECK: (d0, d1, d2) -> (d0) 1278 // CHECK: (d0, d1, d2) -> (d2) 1279 1280 return 0; 1281 } 1282 1283 int printAffineExpr(MlirContext ctx) { 1284 MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 5); 1285 MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 5); 1286 MlirAffineExpr affineConstantExpr = mlirAffineConstantExprGet(ctx, 5); 1287 MlirAffineExpr affineAddExpr = 1288 mlirAffineAddExprGet(affineDimExpr, affineSymbolExpr); 1289 MlirAffineExpr affineMulExpr = 1290 mlirAffineMulExprGet(affineDimExpr, affineSymbolExpr); 1291 MlirAffineExpr affineModExpr = 1292 mlirAffineModExprGet(affineDimExpr, affineSymbolExpr); 1293 MlirAffineExpr affineFloorDivExpr = 1294 mlirAffineFloorDivExprGet(affineDimExpr, affineSymbolExpr); 1295 MlirAffineExpr affineCeilDivExpr = 1296 mlirAffineCeilDivExprGet(affineDimExpr, affineSymbolExpr); 1297 1298 // Tests mlirAffineExprDump. 1299 fprintf(stderr, "@affineExpr\n"); 1300 mlirAffineExprDump(affineDimExpr); 1301 mlirAffineExprDump(affineSymbolExpr); 1302 mlirAffineExprDump(affineConstantExpr); 1303 mlirAffineExprDump(affineAddExpr); 1304 mlirAffineExprDump(affineMulExpr); 1305 mlirAffineExprDump(affineModExpr); 1306 mlirAffineExprDump(affineFloorDivExpr); 1307 mlirAffineExprDump(affineCeilDivExpr); 1308 // CHECK-LABEL: @affineExpr 1309 // CHECK: d5 1310 // CHECK: s5 1311 // CHECK: 5 1312 // CHECK: d5 + s5 1313 // CHECK: d5 * s5 1314 // CHECK: d5 mod s5 1315 // CHECK: d5 floordiv s5 1316 // CHECK: d5 ceildiv s5 1317 1318 // Tests methods of affine binary operation expression, takes add expression 1319 // as an example. 1320 mlirAffineExprDump(mlirAffineBinaryOpExprGetLHS(affineAddExpr)); 1321 mlirAffineExprDump(mlirAffineBinaryOpExprGetRHS(affineAddExpr)); 1322 // CHECK: d5 1323 // CHECK: s5 1324 1325 // Tests methods of affine dimension expression. 1326 if (mlirAffineDimExprGetPosition(affineDimExpr) != 5) 1327 return 1; 1328 1329 // Tests methods of affine symbol expression. 1330 if (mlirAffineSymbolExprGetPosition(affineSymbolExpr) != 5) 1331 return 2; 1332 1333 // Tests methods of affine constant expression. 1334 if (mlirAffineConstantExprGetValue(affineConstantExpr) != 5) 1335 return 3; 1336 1337 // Tests methods of affine expression. 1338 if (mlirAffineExprIsSymbolicOrConstant(affineDimExpr) || 1339 !mlirAffineExprIsSymbolicOrConstant(affineSymbolExpr) || 1340 !mlirAffineExprIsSymbolicOrConstant(affineConstantExpr) || 1341 mlirAffineExprIsSymbolicOrConstant(affineAddExpr) || 1342 mlirAffineExprIsSymbolicOrConstant(affineMulExpr) || 1343 mlirAffineExprIsSymbolicOrConstant(affineModExpr) || 1344 mlirAffineExprIsSymbolicOrConstant(affineFloorDivExpr) || 1345 mlirAffineExprIsSymbolicOrConstant(affineCeilDivExpr)) 1346 return 4; 1347 1348 if (!mlirAffineExprIsPureAffine(affineDimExpr) || 1349 !mlirAffineExprIsPureAffine(affineSymbolExpr) || 1350 !mlirAffineExprIsPureAffine(affineConstantExpr) || 1351 !mlirAffineExprIsPureAffine(affineAddExpr) || 1352 mlirAffineExprIsPureAffine(affineMulExpr) || 1353 mlirAffineExprIsPureAffine(affineModExpr) || 1354 mlirAffineExprIsPureAffine(affineFloorDivExpr) || 1355 mlirAffineExprIsPureAffine(affineCeilDivExpr)) 1356 return 5; 1357 1358 if (mlirAffineExprGetLargestKnownDivisor(affineDimExpr) != 1 || 1359 mlirAffineExprGetLargestKnownDivisor(affineSymbolExpr) != 1 || 1360 mlirAffineExprGetLargestKnownDivisor(affineConstantExpr) != 5 || 1361 mlirAffineExprGetLargestKnownDivisor(affineAddExpr) != 1 || 1362 mlirAffineExprGetLargestKnownDivisor(affineMulExpr) != 1 || 1363 mlirAffineExprGetLargestKnownDivisor(affineModExpr) != 1 || 1364 mlirAffineExprGetLargestKnownDivisor(affineFloorDivExpr) != 1 || 1365 mlirAffineExprGetLargestKnownDivisor(affineCeilDivExpr) != 1) 1366 return 6; 1367 1368 if (!mlirAffineExprIsMultipleOf(affineDimExpr, 1) || 1369 !mlirAffineExprIsMultipleOf(affineSymbolExpr, 1) || 1370 !mlirAffineExprIsMultipleOf(affineConstantExpr, 5) || 1371 !mlirAffineExprIsMultipleOf(affineAddExpr, 1) || 1372 !mlirAffineExprIsMultipleOf(affineMulExpr, 1) || 1373 !mlirAffineExprIsMultipleOf(affineModExpr, 1) || 1374 !mlirAffineExprIsMultipleOf(affineFloorDivExpr, 1) || 1375 !mlirAffineExprIsMultipleOf(affineCeilDivExpr, 1)) 1376 return 7; 1377 1378 if (!mlirAffineExprIsFunctionOfDim(affineDimExpr, 5) || 1379 mlirAffineExprIsFunctionOfDim(affineSymbolExpr, 5) || 1380 mlirAffineExprIsFunctionOfDim(affineConstantExpr, 5) || 1381 !mlirAffineExprIsFunctionOfDim(affineAddExpr, 5) || 1382 !mlirAffineExprIsFunctionOfDim(affineMulExpr, 5) || 1383 !mlirAffineExprIsFunctionOfDim(affineModExpr, 5) || 1384 !mlirAffineExprIsFunctionOfDim(affineFloorDivExpr, 5) || 1385 !mlirAffineExprIsFunctionOfDim(affineCeilDivExpr, 5)) 1386 return 8; 1387 1388 // Tests 'IsA' methods of affine binary operation expression. 1389 if (!mlirAffineExprIsAAdd(affineAddExpr)) 1390 return 9; 1391 1392 if (!mlirAffineExprIsAMul(affineMulExpr)) 1393 return 10; 1394 1395 if (!mlirAffineExprIsAMod(affineModExpr)) 1396 return 11; 1397 1398 if (!mlirAffineExprIsAFloorDiv(affineFloorDivExpr)) 1399 return 12; 1400 1401 if (!mlirAffineExprIsACeilDiv(affineCeilDivExpr)) 1402 return 13; 1403 1404 if (!mlirAffineExprIsABinary(affineAddExpr)) 1405 return 14; 1406 1407 // Test other 'IsA' method on affine expressions. 1408 if (!mlirAffineExprIsAConstant(affineConstantExpr)) 1409 return 15; 1410 1411 if (!mlirAffineExprIsADim(affineDimExpr)) 1412 return 16; 1413 1414 if (!mlirAffineExprIsASymbol(affineSymbolExpr)) 1415 return 17; 1416 1417 // Test equality and nullity. 1418 MlirAffineExpr otherDimExpr = mlirAffineDimExprGet(ctx, 5); 1419 if (!mlirAffineExprEqual(affineDimExpr, otherDimExpr)) 1420 return 18; 1421 1422 if (mlirAffineExprIsNull(affineDimExpr)) 1423 return 19; 1424 1425 return 0; 1426 } 1427 1428 int affineMapFromExprs(MlirContext ctx) { 1429 MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 0); 1430 MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 1); 1431 MlirAffineExpr exprs[] = {affineDimExpr, affineSymbolExpr}; 1432 MlirAffineMap map = mlirAffineMapGet(ctx, 3, 3, 2, exprs); 1433 1434 // CHECK-LABEL: @affineMapFromExprs 1435 fprintf(stderr, "@affineMapFromExprs"); 1436 // CHECK: (d0, d1, d2)[s0, s1, s2] -> (d0, s1) 1437 mlirAffineMapDump(map); 1438 1439 if (mlirAffineMapGetNumResults(map) != 2) 1440 return 1; 1441 1442 if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 0), affineDimExpr)) 1443 return 2; 1444 1445 if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 1), affineSymbolExpr)) 1446 return 3; 1447 1448 MlirAffineExpr affineDim2Expr = mlirAffineDimExprGet(ctx, 1); 1449 MlirAffineExpr composed = mlirAffineExprCompose(affineDim2Expr, map); 1450 // CHECK: s1 1451 mlirAffineExprDump(composed); 1452 if (!mlirAffineExprEqual(composed, affineSymbolExpr)) 1453 return 4; 1454 1455 return 0; 1456 } 1457 1458 int printIntegerSet(MlirContext ctx) { 1459 MlirIntegerSet emptySet = mlirIntegerSetEmptyGet(ctx, 2, 1); 1460 1461 // CHECK-LABEL: @printIntegerSet 1462 fprintf(stderr, "@printIntegerSet"); 1463 1464 // CHECK: (d0, d1)[s0] : (1 == 0) 1465 mlirIntegerSetDump(emptySet); 1466 1467 if (!mlirIntegerSetIsCanonicalEmpty(emptySet)) 1468 return 1; 1469 1470 MlirIntegerSet anotherEmptySet = mlirIntegerSetEmptyGet(ctx, 2, 1); 1471 if (!mlirIntegerSetEqual(emptySet, anotherEmptySet)) 1472 return 2; 1473 1474 // Construct a set constrained by: 1475 // d0 - s0 == 0, 1476 // d1 - 42 >= 0. 1477 MlirAffineExpr negOne = mlirAffineConstantExprGet(ctx, -1); 1478 MlirAffineExpr negFortyTwo = mlirAffineConstantExprGet(ctx, -42); 1479 MlirAffineExpr d0 = mlirAffineDimExprGet(ctx, 0); 1480 MlirAffineExpr d1 = mlirAffineDimExprGet(ctx, 1); 1481 MlirAffineExpr s0 = mlirAffineSymbolExprGet(ctx, 0); 1482 MlirAffineExpr negS0 = mlirAffineMulExprGet(negOne, s0); 1483 MlirAffineExpr d0minusS0 = mlirAffineAddExprGet(d0, negS0); 1484 MlirAffineExpr d1minus42 = mlirAffineAddExprGet(d1, negFortyTwo); 1485 MlirAffineExpr constraints[] = {d0minusS0, d1minus42}; 1486 bool flags[] = {true, false}; 1487 1488 MlirIntegerSet set = mlirIntegerSetGet(ctx, 2, 1, 2, constraints, flags); 1489 // CHECK: (d0, d1)[s0] : ( 1490 // CHECK-DAG: d0 - s0 == 0 1491 // CHECK-DAG: d1 - 42 >= 0 1492 mlirIntegerSetDump(set); 1493 1494 // Transform d1 into s0. 1495 MlirAffineExpr s1 = mlirAffineSymbolExprGet(ctx, 1); 1496 MlirAffineExpr repl[] = {d0, s1}; 1497 MlirIntegerSet replaced = mlirIntegerSetReplaceGet(set, repl, &s0, 1, 2); 1498 // CHECK: (d0)[s0, s1] : ( 1499 // CHECK-DAG: d0 - s0 == 0 1500 // CHECK-DAG: s1 - 42 >= 0 1501 mlirIntegerSetDump(replaced); 1502 1503 if (mlirIntegerSetGetNumDims(set) != 2) 1504 return 3; 1505 if (mlirIntegerSetGetNumDims(replaced) != 1) 1506 return 4; 1507 1508 if (mlirIntegerSetGetNumSymbols(set) != 1) 1509 return 5; 1510 if (mlirIntegerSetGetNumSymbols(replaced) != 2) 1511 return 6; 1512 1513 if (mlirIntegerSetGetNumInputs(set) != 3) 1514 return 7; 1515 1516 if (mlirIntegerSetGetNumConstraints(set) != 2) 1517 return 8; 1518 1519 if (mlirIntegerSetGetNumEqualities(set) != 1) 1520 return 9; 1521 1522 if (mlirIntegerSetGetNumInequalities(set) != 1) 1523 return 10; 1524 1525 MlirAffineExpr cstr1 = mlirIntegerSetGetConstraint(set, 0); 1526 MlirAffineExpr cstr2 = mlirIntegerSetGetConstraint(set, 1); 1527 bool isEq1 = mlirIntegerSetIsConstraintEq(set, 0); 1528 bool isEq2 = mlirIntegerSetIsConstraintEq(set, 1); 1529 if (!mlirAffineExprEqual(cstr1, isEq1 ? d0minusS0 : d1minus42)) 1530 return 11; 1531 if (!mlirAffineExprEqual(cstr2, isEq2 ? d0minusS0 : d1minus42)) 1532 return 12; 1533 1534 return 0; 1535 } 1536 1537 int registerOnlyStd() { 1538 MlirContext ctx = mlirContextCreate(); 1539 // The built-in dialect is always loaded. 1540 if (mlirContextGetNumLoadedDialects(ctx) != 1) 1541 return 1; 1542 1543 MlirDialectHandle stdHandle = mlirGetDialectHandle__func__(); 1544 1545 MlirDialect std = mlirContextGetOrLoadDialect( 1546 ctx, mlirDialectHandleGetNamespace(stdHandle)); 1547 if (!mlirDialectIsNull(std)) 1548 return 2; 1549 1550 mlirDialectHandleRegisterDialect(stdHandle, ctx); 1551 1552 std = mlirContextGetOrLoadDialect(ctx, 1553 mlirDialectHandleGetNamespace(stdHandle)); 1554 if (mlirDialectIsNull(std)) 1555 return 3; 1556 1557 MlirDialect alsoStd = mlirDialectHandleLoadDialect(stdHandle, ctx); 1558 if (!mlirDialectEqual(std, alsoStd)) 1559 return 4; 1560 1561 MlirStringRef stdNs = mlirDialectGetNamespace(std); 1562 MlirStringRef alsoStdNs = mlirDialectHandleGetNamespace(stdHandle); 1563 if (stdNs.length != alsoStdNs.length || 1564 strncmp(stdNs.data, alsoStdNs.data, stdNs.length)) 1565 return 5; 1566 1567 fprintf(stderr, "@registration\n"); 1568 // CHECK-LABEL: @registration 1569 1570 // CHECK: cf.cond_br is_registered: 1 1571 fprintf(stderr, "cf.cond_br is_registered: %d\n", 1572 mlirContextIsRegisteredOperation( 1573 ctx, mlirStringRefCreateFromCString("cf.cond_br"))); 1574 1575 // CHECK: func.not_existing_op is_registered: 0 1576 fprintf(stderr, "func.not_existing_op is_registered: %d\n", 1577 mlirContextIsRegisteredOperation( 1578 ctx, mlirStringRefCreateFromCString("func.not_existing_op"))); 1579 1580 // CHECK: not_existing_dialect.not_existing_op is_registered: 0 1581 fprintf(stderr, "not_existing_dialect.not_existing_op is_registered: %d\n", 1582 mlirContextIsRegisteredOperation( 1583 ctx, mlirStringRefCreateFromCString( 1584 "not_existing_dialect.not_existing_op"))); 1585 1586 mlirContextDestroy(ctx); 1587 return 0; 1588 } 1589 1590 /// Tests backreference APIs 1591 static int testBackreferences() { 1592 fprintf(stderr, "@test_backreferences\n"); 1593 1594 MlirContext ctx = mlirContextCreate(); 1595 mlirContextSetAllowUnregisteredDialects(ctx, true); 1596 MlirLocation loc = mlirLocationUnknownGet(ctx); 1597 1598 MlirOperationState opState = 1599 mlirOperationStateGet(mlirStringRefCreateFromCString("invalid.op"), loc); 1600 MlirRegion region = mlirRegionCreate(); 1601 MlirBlock block = mlirBlockCreate(0, NULL, NULL); 1602 mlirRegionAppendOwnedBlock(region, block); 1603 mlirOperationStateAddOwnedRegions(&opState, 1, ®ion); 1604 MlirOperation op = mlirOperationCreate(&opState); 1605 MlirIdentifier ident = 1606 mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("identifier")); 1607 1608 if (!mlirContextEqual(ctx, mlirOperationGetContext(op))) { 1609 fprintf(stderr, "ERROR: Getting context from operation failed\n"); 1610 return 1; 1611 } 1612 if (!mlirOperationEqual(op, mlirBlockGetParentOperation(block))) { 1613 fprintf(stderr, "ERROR: Getting parent operation from block failed\n"); 1614 return 2; 1615 } 1616 if (!mlirContextEqual(ctx, mlirIdentifierGetContext(ident))) { 1617 fprintf(stderr, "ERROR: Getting context from identifier failed\n"); 1618 return 3; 1619 } 1620 1621 mlirOperationDestroy(op); 1622 mlirContextDestroy(ctx); 1623 1624 // CHECK-LABEL: @test_backreferences 1625 return 0; 1626 } 1627 1628 /// Tests operand APIs. 1629 int testOperands() { 1630 fprintf(stderr, "@testOperands\n"); 1631 // CHECK-LABEL: @testOperands 1632 1633 MlirContext ctx = mlirContextCreate(); 1634 mlirRegisterAllDialects(ctx); 1635 mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("test")); 1636 MlirLocation loc = mlirLocationUnknownGet(ctx); 1637 MlirType indexType = mlirIndexTypeGet(ctx); 1638 1639 // Create some constants to use as operands. 1640 MlirAttribute indexZeroLiteral = 1641 mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index")); 1642 MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet( 1643 mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")), 1644 indexZeroLiteral); 1645 MlirOperationState constZeroState = mlirOperationStateGet( 1646 mlirStringRefCreateFromCString("arith.constant"), loc); 1647 mlirOperationStateAddResults(&constZeroState, 1, &indexType); 1648 mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr); 1649 MlirOperation constZero = mlirOperationCreate(&constZeroState); 1650 MlirValue constZeroValue = mlirOperationGetResult(constZero, 0); 1651 1652 MlirAttribute indexOneLiteral = 1653 mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("1 : index")); 1654 MlirNamedAttribute indexOneValueAttr = mlirNamedAttributeGet( 1655 mlirIdentifierGet(ctx, mlirStringRefCreateFromCString("value")), 1656 indexOneLiteral); 1657 MlirOperationState constOneState = mlirOperationStateGet( 1658 mlirStringRefCreateFromCString("arith.constant"), loc); 1659 mlirOperationStateAddResults(&constOneState, 1, &indexType); 1660 mlirOperationStateAddAttributes(&constOneState, 1, &indexOneValueAttr); 1661 MlirOperation constOne = mlirOperationCreate(&constOneState); 1662 MlirValue constOneValue = mlirOperationGetResult(constOne, 0); 1663 1664 // Create the operation under test. 1665 mlirContextSetAllowUnregisteredDialects(ctx, true); 1666 MlirOperationState opState = 1667 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op"), loc); 1668 MlirValue initialOperands[] = {constZeroValue}; 1669 mlirOperationStateAddOperands(&opState, 1, initialOperands); 1670 MlirOperation op = mlirOperationCreate(&opState); 1671 1672 // Test operand APIs. 1673 intptr_t numOperands = mlirOperationGetNumOperands(op); 1674 fprintf(stderr, "Num Operands: %" PRIdPTR "\n", numOperands); 1675 // CHECK: Num Operands: 1 1676 1677 MlirValue opOperand = mlirOperationGetOperand(op, 0); 1678 fprintf(stderr, "Original operand: "); 1679 mlirValuePrint(opOperand, printToStderr, NULL); 1680 // CHECK: Original operand: {{.+}} arith.constant 0 : index 1681 1682 mlirOperationSetOperand(op, 0, constOneValue); 1683 opOperand = mlirOperationGetOperand(op, 0); 1684 fprintf(stderr, "Updated operand: "); 1685 mlirValuePrint(opOperand, printToStderr, NULL); 1686 // CHECK: Updated operand: {{.+}} arith.constant 1 : index 1687 1688 mlirOperationDestroy(op); 1689 mlirOperationDestroy(constZero); 1690 mlirOperationDestroy(constOne); 1691 mlirContextDestroy(ctx); 1692 1693 return 0; 1694 } 1695 1696 /// Tests clone APIs. 1697 int testClone() { 1698 fprintf(stderr, "@testClone\n"); 1699 // CHECK-LABEL: @testClone 1700 1701 MlirContext ctx = mlirContextCreate(); 1702 mlirRegisterAllDialects(ctx); 1703 mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("func")); 1704 MlirLocation loc = mlirLocationUnknownGet(ctx); 1705 MlirType indexType = mlirIndexTypeGet(ctx); 1706 MlirStringRef valueStringRef = mlirStringRefCreateFromCString("value"); 1707 1708 MlirAttribute indexZeroLiteral = 1709 mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index")); 1710 MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet( 1711 mlirIdentifierGet(ctx, valueStringRef), indexZeroLiteral); 1712 MlirOperationState constZeroState = mlirOperationStateGet( 1713 mlirStringRefCreateFromCString("arith.constant"), loc); 1714 mlirOperationStateAddResults(&constZeroState, 1, &indexType); 1715 mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr); 1716 MlirOperation constZero = mlirOperationCreate(&constZeroState); 1717 1718 MlirAttribute indexOneLiteral = 1719 mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("1 : index")); 1720 MlirOperation constOne = mlirOperationClone(constZero); 1721 mlirOperationSetAttributeByName(constOne, valueStringRef, indexOneLiteral); 1722 1723 mlirOperationPrint(constZero, printToStderr, NULL); 1724 mlirOperationPrint(constOne, printToStderr, NULL); 1725 // CHECK: arith.constant 0 : index 1726 // CHECK: arith.constant 1 : index 1727 1728 mlirOperationDestroy(constZero); 1729 mlirOperationDestroy(constOne); 1730 mlirContextDestroy(ctx); 1731 return 0; 1732 } 1733 1734 // Wraps a diagnostic into additional text we can match against. 1735 MlirLogicalResult errorHandler(MlirDiagnostic diagnostic, void *userData) { 1736 fprintf(stderr, "processing diagnostic (userData: %" PRIdPTR ") <<\n", 1737 (intptr_t)userData); 1738 mlirDiagnosticPrint(diagnostic, printToStderr, NULL); 1739 fprintf(stderr, "\n"); 1740 MlirLocation loc = mlirDiagnosticGetLocation(diagnostic); 1741 mlirLocationPrint(loc, printToStderr, NULL); 1742 assert(mlirDiagnosticGetNumNotes(diagnostic) == 0); 1743 fprintf(stderr, "\n>> end of diagnostic (userData: %" PRIdPTR ")\n", 1744 (intptr_t)userData); 1745 return mlirLogicalResultSuccess(); 1746 } 1747 1748 // Logs when the delete user data callback is called 1749 static void deleteUserData(void *userData) { 1750 fprintf(stderr, "deleting user data (userData: %" PRIdPTR ")\n", 1751 (intptr_t)userData); 1752 } 1753 1754 int testTypeID(MlirContext ctx) { 1755 fprintf(stderr, "@testTypeID\n"); 1756 1757 // Test getting and comparing type and attribute type ids. 1758 MlirType i32 = mlirIntegerTypeGet(ctx, 32); 1759 MlirTypeID i32ID = mlirTypeGetTypeID(i32); 1760 MlirType ui32 = mlirIntegerTypeUnsignedGet(ctx, 32); 1761 MlirTypeID ui32ID = mlirTypeGetTypeID(ui32); 1762 MlirType f32 = mlirF32TypeGet(ctx); 1763 MlirTypeID f32ID = mlirTypeGetTypeID(f32); 1764 MlirAttribute i32Attr = mlirIntegerAttrGet(i32, 1); 1765 MlirTypeID i32AttrID = mlirAttributeGetTypeID(i32Attr); 1766 1767 if (mlirTypeIDIsNull(i32ID) || mlirTypeIDIsNull(ui32ID) || 1768 mlirTypeIDIsNull(f32ID) || mlirTypeIDIsNull(i32AttrID)) { 1769 fprintf(stderr, "ERROR: Expected type ids to be present\n"); 1770 return 1; 1771 } 1772 1773 if (!mlirTypeIDEqual(i32ID, ui32ID) || 1774 mlirTypeIDHashValue(i32ID) != mlirTypeIDHashValue(ui32ID)) { 1775 fprintf( 1776 stderr, 1777 "ERROR: Expected different integer types to have the same type id\n"); 1778 return 2; 1779 } 1780 1781 if (mlirTypeIDEqual(i32ID, f32ID)) { 1782 fprintf(stderr, 1783 "ERROR: Expected integer type id to not equal float type id\n"); 1784 return 3; 1785 } 1786 1787 if (mlirTypeIDEqual(i32ID, i32AttrID)) { 1788 fprintf(stderr, "ERROR: Expected integer type id to not equal integer " 1789 "attribute type id\n"); 1790 return 4; 1791 } 1792 1793 MlirLocation loc = mlirLocationUnknownGet(ctx); 1794 MlirType indexType = mlirIndexTypeGet(ctx); 1795 MlirStringRef valueStringRef = mlirStringRefCreateFromCString("value"); 1796 1797 // Create a registered operation, which should have a type id. 1798 MlirAttribute indexZeroLiteral = 1799 mlirAttributeParseGet(ctx, mlirStringRefCreateFromCString("0 : index")); 1800 MlirNamedAttribute indexZeroValueAttr = mlirNamedAttributeGet( 1801 mlirIdentifierGet(ctx, valueStringRef), indexZeroLiteral); 1802 MlirOperationState constZeroState = mlirOperationStateGet( 1803 mlirStringRefCreateFromCString("arith.constant"), loc); 1804 mlirOperationStateAddResults(&constZeroState, 1, &indexType); 1805 mlirOperationStateAddAttributes(&constZeroState, 1, &indexZeroValueAttr); 1806 MlirOperation constZero = mlirOperationCreate(&constZeroState); 1807 1808 if (!mlirOperationVerify(constZero)) { 1809 fprintf(stderr, "ERROR: Expected operation to verify correctly\n"); 1810 return 5; 1811 } 1812 1813 if (mlirOperationIsNull(constZero)) { 1814 fprintf(stderr, "ERROR: Expected registered operation to be present\n"); 1815 return 6; 1816 } 1817 1818 MlirTypeID registeredOpID = mlirOperationGetTypeID(constZero); 1819 1820 if (mlirTypeIDIsNull(registeredOpID)) { 1821 fprintf(stderr, 1822 "ERROR: Expected registered operation type id to be present\n"); 1823 return 7; 1824 } 1825 1826 // Create an unregistered operation, which should not have a type id. 1827 mlirContextSetAllowUnregisteredDialects(ctx, true); 1828 MlirOperationState opState = 1829 mlirOperationStateGet(mlirStringRefCreateFromCString("dummy.op"), loc); 1830 MlirOperation unregisteredOp = mlirOperationCreate(&opState); 1831 if (mlirOperationIsNull(unregisteredOp)) { 1832 fprintf(stderr, "ERROR: Expected unregistered operation to be present\n"); 1833 return 8; 1834 } 1835 1836 MlirTypeID unregisteredOpID = mlirOperationGetTypeID(unregisteredOp); 1837 1838 if (!mlirTypeIDIsNull(unregisteredOpID)) { 1839 fprintf(stderr, 1840 "ERROR: Expected unregistered operation type id to be null\n"); 1841 return 9; 1842 } 1843 1844 mlirOperationDestroy(constZero); 1845 mlirOperationDestroy(unregisteredOp); 1846 1847 return 0; 1848 } 1849 1850 int testSymbolTable(MlirContext ctx) { 1851 fprintf(stderr, "@testSymbolTable\n"); 1852 1853 const char *moduleString = "func.func private @foo()" 1854 "func.func private @bar()"; 1855 const char *otherModuleString = "func.func private @qux()" 1856 "func.func private @foo()"; 1857 1858 MlirModule module = 1859 mlirModuleCreateParse(ctx, mlirStringRefCreateFromCString(moduleString)); 1860 MlirModule otherModule = mlirModuleCreateParse( 1861 ctx, mlirStringRefCreateFromCString(otherModuleString)); 1862 1863 MlirSymbolTable symbolTable = 1864 mlirSymbolTableCreate(mlirModuleGetOperation(module)); 1865 1866 MlirOperation funcFoo = 1867 mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("foo")); 1868 if (mlirOperationIsNull(funcFoo)) 1869 return 1; 1870 1871 MlirOperation funcBar = 1872 mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("bar")); 1873 if (mlirOperationEqual(funcFoo, funcBar)) 1874 return 2; 1875 1876 MlirOperation missing = 1877 mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("qux")); 1878 if (!mlirOperationIsNull(missing)) 1879 return 3; 1880 1881 MlirBlock moduleBody = mlirModuleGetBody(module); 1882 MlirBlock otherModuleBody = mlirModuleGetBody(otherModule); 1883 MlirOperation operation = mlirBlockGetFirstOperation(otherModuleBody); 1884 mlirOperationRemoveFromParent(operation); 1885 mlirBlockAppendOwnedOperation(moduleBody, operation); 1886 1887 // At this moment, the operation is still missing from the symbol table. 1888 MlirOperation stillMissing = 1889 mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("qux")); 1890 if (!mlirOperationIsNull(stillMissing)) 1891 return 4; 1892 1893 // After it is added to the symbol table, and not only the operation with 1894 // which the table is associated, it can be looked up. 1895 mlirSymbolTableInsert(symbolTable, operation); 1896 MlirOperation funcQux = 1897 mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("qux")); 1898 if (!mlirOperationEqual(operation, funcQux)) 1899 return 5; 1900 1901 // Erasing from the symbol table also removes the operation. 1902 mlirSymbolTableErase(symbolTable, funcBar); 1903 MlirOperation nowMissing = 1904 mlirSymbolTableLookup(symbolTable, mlirStringRefCreateFromCString("bar")); 1905 if (!mlirOperationIsNull(nowMissing)) 1906 return 6; 1907 1908 // Adding a symbol with the same name to the table should rename. 1909 MlirOperation duplicateNameOp = mlirBlockGetFirstOperation(otherModuleBody); 1910 mlirOperationRemoveFromParent(duplicateNameOp); 1911 mlirBlockAppendOwnedOperation(moduleBody, duplicateNameOp); 1912 MlirAttribute newName = mlirSymbolTableInsert(symbolTable, duplicateNameOp); 1913 MlirStringRef newNameStr = mlirStringAttrGetValue(newName); 1914 if (mlirStringRefEqual(newNameStr, mlirStringRefCreateFromCString("foo"))) 1915 return 7; 1916 MlirAttribute updatedName = mlirOperationGetAttributeByName( 1917 duplicateNameOp, mlirSymbolTableGetSymbolAttributeName()); 1918 if (!mlirAttributeEqual(updatedName, newName)) 1919 return 8; 1920 1921 mlirOperationDump(mlirModuleGetOperation(module)); 1922 mlirOperationDump(mlirModuleGetOperation(otherModule)); 1923 // clang-format off 1924 // CHECK-LABEL: @testSymbolTable 1925 // CHECK: module 1926 // CHECK: func private @foo 1927 // CHECK: func private @qux 1928 // CHECK: func private @foo{{.+}} 1929 // CHECK: module 1930 // CHECK-NOT: @qux 1931 // CHECK-NOT: @foo 1932 // clang-format on 1933 1934 mlirSymbolTableDestroy(symbolTable); 1935 mlirModuleDestroy(module); 1936 mlirModuleDestroy(otherModule); 1937 1938 return 0; 1939 } 1940 1941 int testDialectRegistry() { 1942 fprintf(stderr, "@testDialectRegistry\n"); 1943 1944 MlirDialectRegistry registry = mlirDialectRegistryCreate(); 1945 if (mlirDialectRegistryIsNull(registry)) { 1946 fprintf(stderr, "ERROR: Expected registry to be present\n"); 1947 return 1; 1948 } 1949 1950 MlirDialectHandle stdHandle = mlirGetDialectHandle__func__(); 1951 mlirDialectHandleInsertDialect(stdHandle, registry); 1952 1953 MlirContext ctx = mlirContextCreate(); 1954 if (mlirContextGetNumRegisteredDialects(ctx) != 0) { 1955 fprintf(stderr, 1956 "ERROR: Expected no dialects to be registered to new context\n"); 1957 } 1958 1959 mlirContextAppendDialectRegistry(ctx, registry); 1960 if (mlirContextGetNumRegisteredDialects(ctx) != 1) { 1961 fprintf(stderr, "ERROR: Expected the dialect in the registry to be " 1962 "registered to the context\n"); 1963 } 1964 1965 mlirContextDestroy(ctx); 1966 mlirDialectRegistryDestroy(registry); 1967 1968 return 0; 1969 } 1970 1971 void testDiagnostics() { 1972 MlirContext ctx = mlirContextCreate(); 1973 MlirDiagnosticHandlerID id = mlirContextAttachDiagnosticHandler( 1974 ctx, errorHandler, (void *)42, deleteUserData); 1975 fprintf(stderr, "@test_diagnostics\n"); 1976 MlirLocation unknownLoc = mlirLocationUnknownGet(ctx); 1977 mlirEmitError(unknownLoc, "test diagnostics"); 1978 MlirLocation fileLineColLoc = mlirLocationFileLineColGet( 1979 ctx, mlirStringRefCreateFromCString("file.c"), 1, 2); 1980 mlirEmitError(fileLineColLoc, "test diagnostics"); 1981 MlirLocation callSiteLoc = mlirLocationCallSiteGet( 1982 mlirLocationFileLineColGet( 1983 ctx, mlirStringRefCreateFromCString("other-file.c"), 2, 3), 1984 fileLineColLoc); 1985 mlirEmitError(callSiteLoc, "test diagnostics"); 1986 MlirLocation null = {0}; 1987 MlirLocation nameLoc = 1988 mlirLocationNameGet(ctx, mlirStringRefCreateFromCString("named"), null); 1989 mlirEmitError(nameLoc, "test diagnostics"); 1990 MlirLocation locs[2] = {nameLoc, callSiteLoc}; 1991 MlirAttribute nullAttr = {0}; 1992 MlirLocation fusedLoc = mlirLocationFusedGet(ctx, 2, locs, nullAttr); 1993 mlirEmitError(fusedLoc, "test diagnostics"); 1994 mlirContextDetachDiagnosticHandler(ctx, id); 1995 mlirEmitError(unknownLoc, "more test diagnostics"); 1996 // CHECK-LABEL: @test_diagnostics 1997 // CHECK: processing diagnostic (userData: 42) << 1998 // CHECK: test diagnostics 1999 // CHECK: loc(unknown) 2000 // CHECK: >> end of diagnostic (userData: 42) 2001 // CHECK: processing diagnostic (userData: 42) << 2002 // CHECK: test diagnostics 2003 // CHECK: loc("file.c":1:2) 2004 // CHECK: >> end of diagnostic (userData: 42) 2005 // CHECK: processing diagnostic (userData: 42) << 2006 // CHECK: test diagnostics 2007 // CHECK: loc(callsite("other-file.c":2:3 at "file.c":1:2)) 2008 // CHECK: >> end of diagnostic (userData: 42) 2009 // CHECK: processing diagnostic (userData: 42) << 2010 // CHECK: test diagnostics 2011 // CHECK: loc("named") 2012 // CHECK: >> end of diagnostic (userData: 42) 2013 // CHECK: processing diagnostic (userData: 42) << 2014 // CHECK: test diagnostics 2015 // CHECK: loc(fused["named", callsite("other-file.c":2:3 at "file.c":1:2)]) 2016 // CHECK: deleting user data (userData: 42) 2017 // CHECK-NOT: processing diagnostic 2018 // CHECK: more test diagnostics 2019 mlirContextDestroy(ctx); 2020 } 2021 2022 int main() { 2023 MlirContext ctx = mlirContextCreate(); 2024 mlirRegisterAllDialects(ctx); 2025 if (constructAndTraverseIr(ctx)) 2026 return 1; 2027 buildWithInsertionsAndPrint(ctx); 2028 if (createOperationWithTypeInference(ctx)) 2029 return 2; 2030 2031 if (printBuiltinTypes(ctx)) 2032 return 3; 2033 if (printBuiltinAttributes(ctx)) 2034 return 4; 2035 if (printAffineMap(ctx)) 2036 return 5; 2037 if (printAffineExpr(ctx)) 2038 return 6; 2039 if (affineMapFromExprs(ctx)) 2040 return 7; 2041 if (printIntegerSet(ctx)) 2042 return 8; 2043 if (registerOnlyStd()) 2044 return 9; 2045 if (testBackreferences()) 2046 return 10; 2047 if (testOperands()) 2048 return 11; 2049 if (testClone()) 2050 return 12; 2051 if (testTypeID(ctx)) 2052 return 13; 2053 if (testSymbolTable(ctx)) 2054 return 14; 2055 if (testDialectRegistry()) 2056 return 15; 2057 2058 mlirContextDestroy(ctx); 2059 2060 testDiagnostics(); 2061 return 0; 2062 } 2063