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